Merge commit 'ce5870a3a8f2b10668ee4f04c2ae0287f66f31b2'
* commit 'ce5870a3a8f2b10668ee4f04c2ae0287f66f31b2': cbs: Refcount all the things! Some changes for bitstream API. Merged-by: Mark Thompson <sw@jkqxz.net>
This commit is contained in:
commit
0cc8e34a94
173
libavcodec/cbs.c
173
libavcodec/cbs.c
@ -21,6 +21,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "libavutil/avassert.h"
|
#include "libavutil/avassert.h"
|
||||||
|
#include "libavutil/buffer.h"
|
||||||
#include "libavutil/common.h"
|
#include "libavutil/common.h"
|
||||||
|
|
||||||
#include "cbs.h"
|
#include "cbs.h"
|
||||||
@ -95,11 +96,12 @@ void ff_cbs_close(CodedBitstreamContext **ctx_ptr)
|
|||||||
static void cbs_unit_uninit(CodedBitstreamContext *ctx,
|
static void cbs_unit_uninit(CodedBitstreamContext *ctx,
|
||||||
CodedBitstreamUnit *unit)
|
CodedBitstreamUnit *unit)
|
||||||
{
|
{
|
||||||
if (ctx->codec->free_unit && unit->content && !unit->content_external)
|
av_buffer_unref(&unit->content_ref);
|
||||||
ctx->codec->free_unit(unit);
|
unit->content = NULL;
|
||||||
|
|
||||||
av_freep(&unit->data);
|
av_buffer_unref(&unit->data_ref);
|
||||||
unit->data_size = 0;
|
unit->data = NULL;
|
||||||
|
unit->data_size = 0;
|
||||||
unit->data_bit_padding = 0;
|
unit->data_bit_padding = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +115,8 @@ void ff_cbs_fragment_uninit(CodedBitstreamContext *ctx,
|
|||||||
av_freep(&frag->units);
|
av_freep(&frag->units);
|
||||||
frag->nb_units = 0;
|
frag->nb_units = 0;
|
||||||
|
|
||||||
av_freep(&frag->data);
|
av_buffer_unref(&frag->data_ref);
|
||||||
|
frag->data = NULL;
|
||||||
frag->data_size = 0;
|
frag->data_size = 0;
|
||||||
frag->data_bit_padding = 0;
|
frag->data_bit_padding = 0;
|
||||||
}
|
}
|
||||||
@ -133,6 +136,9 @@ static int cbs_read_fragment_content(CodedBitstreamContext *ctx,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
av_buffer_unref(&frag->units[i].content_ref);
|
||||||
|
frag->units[i].content = NULL;
|
||||||
|
|
||||||
err = ctx->codec->read_unit(ctx, &frag->units[i]);
|
err = ctx->codec->read_unit(ctx, &frag->units[i]);
|
||||||
if (err == AVERROR(ENOSYS)) {
|
if (err == AVERROR(ENOSYS)) {
|
||||||
av_log(ctx->log_ctx, AV_LOG_VERBOSE,
|
av_log(ctx->log_ctx, AV_LOG_VERBOSE,
|
||||||
@ -169,6 +175,27 @@ int ff_cbs_read_extradata(CodedBitstreamContext *ctx,
|
|||||||
return cbs_read_fragment_content(ctx, frag);
|
return cbs_read_fragment_content(ctx, frag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cbs_fill_fragment_data(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamFragment *frag,
|
||||||
|
const uint8_t *data, size_t size)
|
||||||
|
{
|
||||||
|
av_assert0(!frag->data && !frag->data_ref);
|
||||||
|
|
||||||
|
frag->data_ref =
|
||||||
|
av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
|
||||||
|
if (!frag->data_ref)
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
|
frag->data = frag->data_ref->data;
|
||||||
|
frag->data_size = size;
|
||||||
|
|
||||||
|
memcpy(frag->data, data, size);
|
||||||
|
memset(frag->data + size, 0,
|
||||||
|
AV_INPUT_BUFFER_PADDING_SIZE);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int ff_cbs_read_packet(CodedBitstreamContext *ctx,
|
int ff_cbs_read_packet(CodedBitstreamContext *ctx,
|
||||||
CodedBitstreamFragment *frag,
|
CodedBitstreamFragment *frag,
|
||||||
const AVPacket *pkt)
|
const AVPacket *pkt)
|
||||||
@ -177,16 +204,24 @@ int ff_cbs_read_packet(CodedBitstreamContext *ctx,
|
|||||||
|
|
||||||
memset(frag, 0, sizeof(*frag));
|
memset(frag, 0, sizeof(*frag));
|
||||||
|
|
||||||
frag->data = pkt->data;
|
if (pkt->buf) {
|
||||||
frag->data_size = pkt->size;
|
frag->data_ref = av_buffer_ref(pkt->buf);
|
||||||
|
if (!frag->data_ref)
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
|
frag->data = pkt->data;
|
||||||
|
frag->data_size = pkt->size;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
err = cbs_fill_fragment_data(ctx, frag, pkt->data, pkt->size);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
err = ctx->codec->split_fragment(ctx, frag, 0);
|
err = ctx->codec->split_fragment(ctx, frag, 0);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
frag->data = NULL;
|
|
||||||
frag->data_size = 0;
|
|
||||||
|
|
||||||
return cbs_read_fragment_content(ctx, frag);
|
return cbs_read_fragment_content(ctx, frag);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,17 +233,14 @@ int ff_cbs_read(CodedBitstreamContext *ctx,
|
|||||||
|
|
||||||
memset(frag, 0, sizeof(*frag));
|
memset(frag, 0, sizeof(*frag));
|
||||||
|
|
||||||
// (We won't write to this during split.)
|
err = cbs_fill_fragment_data(ctx, frag, data, size);
|
||||||
frag->data = (uint8_t*)data;
|
if (err < 0)
|
||||||
frag->data_size = size;
|
return err;
|
||||||
|
|
||||||
err = ctx->codec->split_fragment(ctx, frag, 0);
|
err = ctx->codec->split_fragment(ctx, frag, 0);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
frag->data = NULL;
|
|
||||||
frag->data_size = 0;
|
|
||||||
|
|
||||||
return cbs_read_fragment_content(ctx, frag);
|
return cbs_read_fragment_content(ctx, frag);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,17 +251,25 @@ int ff_cbs_write_fragment_data(CodedBitstreamContext *ctx,
|
|||||||
int err, i;
|
int err, i;
|
||||||
|
|
||||||
for (i = 0; i < frag->nb_units; i++) {
|
for (i = 0; i < frag->nb_units; i++) {
|
||||||
if (!frag->units[i].content)
|
CodedBitstreamUnit *unit = &frag->units[i];
|
||||||
|
|
||||||
|
if (!unit->content)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
err = ctx->codec->write_unit(ctx, &frag->units[i]);
|
av_buffer_unref(&unit->data_ref);
|
||||||
|
unit->data = NULL;
|
||||||
|
|
||||||
|
err = ctx->codec->write_unit(ctx, unit);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to write unit %d "
|
av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to write unit %d "
|
||||||
"(type %"PRIu32").\n", i, frag->units[i].type);
|
"(type %"PRIu32").\n", i, unit->type);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
av_buffer_unref(&frag->data_ref);
|
||||||
|
frag->data = NULL;
|
||||||
|
|
||||||
err = ctx->codec->assemble_fragment(ctx, frag);
|
err = ctx->codec->assemble_fragment(ctx, frag);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to assemble fragment.\n");
|
av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to assemble fragment.\n");
|
||||||
@ -394,6 +434,45 @@ int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ff_cbs_alloc_unit_content(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamUnit *unit,
|
||||||
|
size_t size,
|
||||||
|
void (*free)(void *opaque, uint8_t *data))
|
||||||
|
{
|
||||||
|
av_assert0(!unit->content && !unit->content_ref);
|
||||||
|
|
||||||
|
unit->content = av_mallocz(size);
|
||||||
|
if (!unit->content)
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
|
unit->content_ref = av_buffer_create(unit->content, size,
|
||||||
|
free, ctx, 0);
|
||||||
|
if (!unit->content_ref) {
|
||||||
|
av_freep(&unit->content);
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ff_cbs_alloc_unit_data(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamUnit *unit,
|
||||||
|
size_t size)
|
||||||
|
{
|
||||||
|
av_assert0(!unit->data && !unit->data_ref);
|
||||||
|
|
||||||
|
unit->data_ref = av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
|
||||||
|
if (!unit->data_ref)
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
|
unit->data = unit->data_ref->data;
|
||||||
|
unit->data_size = size;
|
||||||
|
|
||||||
|
memset(unit->data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int cbs_insert_unit(CodedBitstreamContext *ctx,
|
static int cbs_insert_unit(CodedBitstreamContext *ctx,
|
||||||
CodedBitstreamFragment *frag,
|
CodedBitstreamFragment *frag,
|
||||||
int position)
|
int position)
|
||||||
@ -423,21 +502,35 @@ int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx,
|
|||||||
CodedBitstreamFragment *frag,
|
CodedBitstreamFragment *frag,
|
||||||
int position,
|
int position,
|
||||||
CodedBitstreamUnitType type,
|
CodedBitstreamUnitType type,
|
||||||
void *content)
|
void *content,
|
||||||
|
AVBufferRef *content_buf)
|
||||||
{
|
{
|
||||||
|
CodedBitstreamUnit *unit;
|
||||||
|
AVBufferRef *content_ref;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (position == -1)
|
if (position == -1)
|
||||||
position = frag->nb_units;
|
position = frag->nb_units;
|
||||||
av_assert0(position >= 0 && position <= frag->nb_units);
|
av_assert0(position >= 0 && position <= frag->nb_units);
|
||||||
|
|
||||||
err = cbs_insert_unit(ctx, frag, position);
|
if (content_buf) {
|
||||||
if (err < 0)
|
content_ref = av_buffer_ref(content_buf);
|
||||||
return err;
|
if (!content_ref)
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
} else {
|
||||||
|
content_ref = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
frag->units[position].type = type;
|
err = cbs_insert_unit(ctx, frag, position);
|
||||||
frag->units[position].content = content;
|
if (err < 0) {
|
||||||
frag->units[position].content_external = 1;
|
av_buffer_unref(&content_ref);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
unit = &frag->units[position];
|
||||||
|
unit->type = type;
|
||||||
|
unit->content = content;
|
||||||
|
unit->content_ref = content_ref;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -446,21 +539,35 @@ int ff_cbs_insert_unit_data(CodedBitstreamContext *ctx,
|
|||||||
CodedBitstreamFragment *frag,
|
CodedBitstreamFragment *frag,
|
||||||
int position,
|
int position,
|
||||||
CodedBitstreamUnitType type,
|
CodedBitstreamUnitType type,
|
||||||
uint8_t *data, size_t data_size)
|
uint8_t *data, size_t data_size,
|
||||||
|
AVBufferRef *data_buf)
|
||||||
{
|
{
|
||||||
|
CodedBitstreamUnit *unit;
|
||||||
|
AVBufferRef *data_ref;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (position == -1)
|
if (position == -1)
|
||||||
position = frag->nb_units;
|
position = frag->nb_units;
|
||||||
av_assert0(position >= 0 && position <= frag->nb_units);
|
av_assert0(position >= 0 && position <= frag->nb_units);
|
||||||
|
|
||||||
err = cbs_insert_unit(ctx, frag, position);
|
if (data_buf)
|
||||||
if (err < 0)
|
data_ref = av_buffer_ref(data_buf);
|
||||||
return err;
|
else
|
||||||
|
data_ref = av_buffer_create(data, data_size, NULL, NULL, 0);
|
||||||
|
if (!data_ref)
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
frag->units[position].type = type;
|
err = cbs_insert_unit(ctx, frag, position);
|
||||||
frag->units[position].data = data;
|
if (err < 0) {
|
||||||
frag->units[position].data_size = data_size;
|
av_buffer_unref(&data_ref);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
unit = &frag->units[position];
|
||||||
|
unit->type = type;
|
||||||
|
unit->data = data;
|
||||||
|
unit->data_size = data_size;
|
||||||
|
unit->data_ref = data_ref;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "libavutil/buffer.h"
|
||||||
|
|
||||||
#include "avcodec.h"
|
#include "avcodec.h"
|
||||||
|
|
||||||
|
|
||||||
@ -81,6 +83,11 @@ typedef struct CodedBitstreamUnit {
|
|||||||
* This supports non-byte-aligned bitstreams.
|
* This supports non-byte-aligned bitstreams.
|
||||||
*/
|
*/
|
||||||
size_t data_bit_padding;
|
size_t data_bit_padding;
|
||||||
|
/**
|
||||||
|
* If data is reference counted, a reference to the buffer containing
|
||||||
|
* data. Null if data is not reference counted.
|
||||||
|
*/
|
||||||
|
AVBufferRef *data_ref;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pointer to the decomposed form of this unit.
|
* Pointer to the decomposed form of this unit.
|
||||||
@ -91,11 +98,10 @@ typedef struct CodedBitstreamUnit {
|
|||||||
*/
|
*/
|
||||||
void *content;
|
void *content;
|
||||||
/**
|
/**
|
||||||
* Whether the content was supplied externally.
|
* If content is reference counted, a reference to the buffer containing
|
||||||
*
|
* content. Null if content is not reference counted.
|
||||||
* If so, it should not be freed when freeing the unit.
|
|
||||||
*/
|
*/
|
||||||
int content_external;
|
AVBufferRef *content_ref;
|
||||||
} CodedBitstreamUnit;
|
} CodedBitstreamUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -123,6 +129,11 @@ typedef struct CodedBitstreamFragment {
|
|||||||
* The number of bits which should be ignored in the final byte.
|
* The number of bits which should be ignored in the final byte.
|
||||||
*/
|
*/
|
||||||
size_t data_bit_padding;
|
size_t data_bit_padding;
|
||||||
|
/**
|
||||||
|
* If data is reference counted, a reference to the buffer containing
|
||||||
|
* data. Null if data is not reference counted.
|
||||||
|
*/
|
||||||
|
AVBufferRef *data_ref;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of units in this fragment.
|
* Number of units in this fragment.
|
||||||
@ -278,28 +289,50 @@ void ff_cbs_fragment_uninit(CodedBitstreamContext *ctx,
|
|||||||
CodedBitstreamFragment *frag);
|
CodedBitstreamFragment *frag);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate a new internal content buffer of the given size in the unit.
|
||||||
|
*
|
||||||
|
* The content will be zeroed.
|
||||||
|
*/
|
||||||
|
int ff_cbs_alloc_unit_content(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamUnit *unit,
|
||||||
|
size_t size,
|
||||||
|
void (*free)(void *unit, uint8_t *content));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate a new internal data buffer of the given size in the unit.
|
||||||
|
*
|
||||||
|
* The data buffer will have input padding.
|
||||||
|
*/
|
||||||
|
int ff_cbs_alloc_unit_data(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamUnit *unit,
|
||||||
|
size_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert a new unit into a fragment with the given content.
|
* Insert a new unit into a fragment with the given content.
|
||||||
*
|
*
|
||||||
* The content structure continues to be owned by the caller, and
|
* The content structure continues to be owned by the caller if
|
||||||
* will not be freed when the unit is.
|
* content_buf is not supplied.
|
||||||
*/
|
*/
|
||||||
int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx,
|
int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx,
|
||||||
CodedBitstreamFragment *frag,
|
CodedBitstreamFragment *frag,
|
||||||
int position,
|
int position,
|
||||||
CodedBitstreamUnitType type,
|
CodedBitstreamUnitType type,
|
||||||
void *content);
|
void *content,
|
||||||
|
AVBufferRef *content_buf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert a new unit into a fragment with the given data bitstream.
|
* Insert a new unit into a fragment with the given data bitstream.
|
||||||
*
|
*
|
||||||
* The data buffer will be owned by the unit after this operation.
|
* If data_buf is not supplied then data must have been allocated with
|
||||||
|
* av_malloc() and will become owned by the unit after this call.
|
||||||
*/
|
*/
|
||||||
int ff_cbs_insert_unit_data(CodedBitstreamContext *ctx,
|
int ff_cbs_insert_unit_data(CodedBitstreamContext *ctx,
|
||||||
CodedBitstreamFragment *frag,
|
CodedBitstreamFragment *frag,
|
||||||
int position,
|
int position,
|
||||||
CodedBitstreamUnitType type,
|
CodedBitstreamUnitType type,
|
||||||
uint8_t *data, size_t data_size);
|
uint8_t *data, size_t data_size,
|
||||||
|
AVBufferRef *data_buf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a unit from a fragment and free all memory it uses.
|
* Delete a unit from a fragment and free all memory it uses.
|
||||||
|
@ -266,12 +266,14 @@ typedef struct H264RawSEIUserDataRegistered {
|
|||||||
uint8_t itu_t_t35_country_code_extension_byte;
|
uint8_t itu_t_t35_country_code_extension_byte;
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
size_t data_length;
|
size_t data_length;
|
||||||
|
AVBufferRef *data_ref;
|
||||||
} H264RawSEIUserDataRegistered;
|
} H264RawSEIUserDataRegistered;
|
||||||
|
|
||||||
typedef struct H264RawSEIUserDataUnregistered {
|
typedef struct H264RawSEIUserDataUnregistered {
|
||||||
uint8_t uuid_iso_iec_11578[16];
|
uint8_t uuid_iso_iec_11578[16];
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
size_t data_length;
|
size_t data_length;
|
||||||
|
AVBufferRef *data_ref;
|
||||||
} H264RawSEIUserDataUnregistered;
|
} H264RawSEIUserDataUnregistered;
|
||||||
|
|
||||||
typedef struct H264RawSEIRecoveryPoint {
|
typedef struct H264RawSEIRecoveryPoint {
|
||||||
@ -304,6 +306,7 @@ typedef struct H264RawSEIPayload {
|
|||||||
struct {
|
struct {
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
size_t data_length;
|
size_t data_length;
|
||||||
|
AVBufferRef *data_ref;
|
||||||
} other;
|
} other;
|
||||||
} payload;
|
} payload;
|
||||||
} H264RawSEIPayload;
|
} H264RawSEIPayload;
|
||||||
@ -399,6 +402,7 @@ typedef struct H264RawSlice {
|
|||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
size_t data_size;
|
size_t data_size;
|
||||||
int data_bit_start;
|
int data_bit_start;
|
||||||
|
AVBufferRef *data_ref;
|
||||||
} H264RawSlice;
|
} H264RawSlice;
|
||||||
|
|
||||||
|
|
||||||
|
@ -291,9 +291,10 @@ static int cbs_h2645_read_more_rbsp_data(GetBitContext *gbc)
|
|||||||
#define byte_alignment(rw) (get_bits_count(rw) % 8)
|
#define byte_alignment(rw) (get_bits_count(rw) % 8)
|
||||||
|
|
||||||
#define allocate(name, size) do { \
|
#define allocate(name, size) do { \
|
||||||
name = av_mallocz(size); \
|
name ## _ref = av_buffer_allocz(size); \
|
||||||
if (!name) \
|
if (!name ## _ref) \
|
||||||
return AVERROR(ENOMEM); \
|
return AVERROR(ENOMEM); \
|
||||||
|
name = name ## _ref->data; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define FUNC(name) FUNC_H264(READWRITE, name)
|
#define FUNC(name) FUNC_H264(READWRITE, name)
|
||||||
@ -393,82 +394,68 @@ static int cbs_h2645_read_more_rbsp_data(GetBitContext *gbc)
|
|||||||
#undef allocate
|
#undef allocate
|
||||||
|
|
||||||
|
|
||||||
static void cbs_h264_free_sei(H264RawSEI *sei)
|
static void cbs_h264_free_sei_payload(H264RawSEIPayload *payload)
|
||||||
{
|
{
|
||||||
|
switch (payload->payload_type) {
|
||||||
|
case H264_SEI_TYPE_BUFFERING_PERIOD:
|
||||||
|
case H264_SEI_TYPE_PIC_TIMING:
|
||||||
|
case H264_SEI_TYPE_RECOVERY_POINT:
|
||||||
|
case H264_SEI_TYPE_DISPLAY_ORIENTATION:
|
||||||
|
break;
|
||||||
|
case H264_SEI_TYPE_USER_DATA_REGISTERED:
|
||||||
|
av_buffer_unref(&payload->payload.user_data_registered.data_ref);
|
||||||
|
break;
|
||||||
|
case H264_SEI_TYPE_USER_DATA_UNREGISTERED:
|
||||||
|
av_buffer_unref(&payload->payload.user_data_unregistered.data_ref);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
av_buffer_unref(&payload->payload.other.data_ref);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cbs_h264_free_sei(void *unit, uint8_t *content)
|
||||||
|
{
|
||||||
|
H264RawSEI *sei = (H264RawSEI*)content;
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < sei->payload_count; i++) {
|
for (i = 0; i < sei->payload_count; i++)
|
||||||
H264RawSEIPayload *payload = &sei->payload[i];
|
cbs_h264_free_sei_payload(&sei->payload[i]);
|
||||||
|
av_freep(&content);
|
||||||
switch (payload->payload_type) {
|
|
||||||
case H264_SEI_TYPE_BUFFERING_PERIOD:
|
|
||||||
case H264_SEI_TYPE_PIC_TIMING:
|
|
||||||
case H264_SEI_TYPE_RECOVERY_POINT:
|
|
||||||
case H264_SEI_TYPE_DISPLAY_ORIENTATION:
|
|
||||||
break;
|
|
||||||
case H264_SEI_TYPE_USER_DATA_REGISTERED:
|
|
||||||
av_freep(&payload->payload.user_data_registered.data);
|
|
||||||
break;
|
|
||||||
case H264_SEI_TYPE_USER_DATA_UNREGISTERED:
|
|
||||||
av_freep(&payload->payload.user_data_unregistered.data);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
av_freep(&payload->payload.other.data);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cbs_h264_free_slice(H264RawSlice *slice)
|
static void cbs_h264_free_slice(void *unit, uint8_t *content)
|
||||||
{
|
{
|
||||||
av_freep(&slice->data);
|
H264RawSlice *slice = (H264RawSlice*)content;
|
||||||
|
av_buffer_unref(&slice->data_ref);
|
||||||
|
av_freep(&content);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cbs_h264_free_nal_unit(CodedBitstreamUnit *unit)
|
static void cbs_h265_free_vps(void *unit, uint8_t *content)
|
||||||
{
|
{
|
||||||
switch (unit->type) {
|
H265RawVPS *vps = (H265RawVPS*)content;
|
||||||
case H264_NAL_SEI:
|
av_buffer_unref(&vps->extension_data.data_ref);
|
||||||
cbs_h264_free_sei(unit->content);
|
av_freep(&content);
|
||||||
break;
|
|
||||||
case H264_NAL_IDR_SLICE:
|
|
||||||
case H264_NAL_SLICE:
|
|
||||||
cbs_h264_free_slice(unit->content);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
av_freep(&unit->content);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cbs_h265_free_nal_unit(CodedBitstreamUnit *unit)
|
static void cbs_h265_free_sps(void *unit, uint8_t *content)
|
||||||
{
|
{
|
||||||
switch (unit->type) {
|
H265RawSPS *sps = (H265RawSPS*)content;
|
||||||
case HEVC_NAL_VPS:
|
av_buffer_unref(&sps->extension_data.data_ref);
|
||||||
av_freep(&((H265RawVPS*)unit->content)->extension_data.data);
|
av_freep(&content);
|
||||||
break;
|
}
|
||||||
case HEVC_NAL_SPS:
|
|
||||||
av_freep(&((H265RawSPS*)unit->content)->extension_data.data);
|
static void cbs_h265_free_pps(void *unit, uint8_t *content)
|
||||||
break;
|
{
|
||||||
case HEVC_NAL_PPS:
|
H265RawPPS *pps = (H265RawPPS*)content;
|
||||||
av_freep(&((H265RawPPS*)unit->content)->extension_data.data);
|
av_buffer_unref(&pps->extension_data.data_ref);
|
||||||
break;
|
av_freep(&content);
|
||||||
case HEVC_NAL_TRAIL_N:
|
}
|
||||||
case HEVC_NAL_TRAIL_R:
|
|
||||||
case HEVC_NAL_TSA_N:
|
static void cbs_h265_free_slice(void *unit, uint8_t *content)
|
||||||
case HEVC_NAL_TSA_R:
|
{
|
||||||
case HEVC_NAL_STSA_N:
|
H265RawSlice *slice = (H265RawSlice*)content;
|
||||||
case HEVC_NAL_STSA_R:
|
av_buffer_unref(&slice->data_ref);
|
||||||
case HEVC_NAL_RADL_N:
|
av_freep(&content);
|
||||||
case HEVC_NAL_RADL_R:
|
|
||||||
case HEVC_NAL_RASL_N:
|
|
||||||
case HEVC_NAL_RASL_R:
|
|
||||||
case HEVC_NAL_BLA_W_LP:
|
|
||||||
case HEVC_NAL_BLA_W_RADL:
|
|
||||||
case HEVC_NAL_BLA_N_LP:
|
|
||||||
case HEVC_NAL_IDR_W_RADL:
|
|
||||||
case HEVC_NAL_IDR_N_LP:
|
|
||||||
case HEVC_NAL_CRA_NUT:
|
|
||||||
av_freep(&((H265RawSlice*)unit->content)->data);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
av_freep(&unit->content);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cbs_h2645_fragment_add_nals(CodedBitstreamContext *ctx,
|
static int cbs_h2645_fragment_add_nals(CodedBitstreamContext *ctx,
|
||||||
@ -494,7 +481,7 @@ static int cbs_h2645_fragment_add_nals(CodedBitstreamContext *ctx,
|
|||||||
memset(data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
|
memset(data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
|
||||||
|
|
||||||
err = ff_cbs_insert_unit_data(ctx, frag, -1, nal->type,
|
err = ff_cbs_insert_unit_data(ctx, frag, -1, nal->type,
|
||||||
data, size);
|
data, size, NULL);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
av_freep(&data);
|
av_freep(&data);
|
||||||
return err;
|
return err;
|
||||||
@ -705,35 +692,32 @@ static int cbs_h264_read_nal_unit(CodedBitstreamContext *ctx,
|
|||||||
{
|
{
|
||||||
H264RawSPS *sps;
|
H264RawSPS *sps;
|
||||||
|
|
||||||
sps = av_mallocz(sizeof(*sps));
|
err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*sps), NULL);
|
||||||
if (!sps)
|
if (err < 0)
|
||||||
return AVERROR(ENOMEM);
|
|
||||||
err = cbs_h264_read_sps(ctx, &gbc, sps);
|
|
||||||
if (err >= 0)
|
|
||||||
err = cbs_h264_replace_sps(ctx, sps);
|
|
||||||
if (err < 0) {
|
|
||||||
av_free(sps);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
sps = unit->content;
|
||||||
|
|
||||||
unit->content = sps;
|
err = cbs_h264_read_sps(ctx, &gbc, sps);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = cbs_h264_replace_sps(ctx, sps);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case H264_NAL_SPS_EXT:
|
case H264_NAL_SPS_EXT:
|
||||||
{
|
{
|
||||||
H264RawSPSExtension *sps_ext;
|
err = ff_cbs_alloc_unit_content(ctx, unit,
|
||||||
|
sizeof(H264RawSPSExtension),
|
||||||
sps_ext = av_mallocz(sizeof(*sps_ext));
|
NULL);
|
||||||
if (!sps_ext)
|
if (err < 0)
|
||||||
return AVERROR(ENOMEM);
|
|
||||||
err = cbs_h264_read_sps_extension(ctx, &gbc, sps_ext);
|
|
||||||
if (err < 0) {
|
|
||||||
av_free(sps_ext);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
|
||||||
|
|
||||||
unit->content = sps_ext;
|
err = cbs_h264_read_sps_extension(ctx, &gbc, unit->content);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -741,18 +725,18 @@ static int cbs_h264_read_nal_unit(CodedBitstreamContext *ctx,
|
|||||||
{
|
{
|
||||||
H264RawPPS *pps;
|
H264RawPPS *pps;
|
||||||
|
|
||||||
pps = av_mallocz(sizeof(*pps));
|
err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*pps), NULL);
|
||||||
if (!pps)
|
if (err < 0)
|
||||||
return AVERROR(ENOMEM);
|
|
||||||
err = cbs_h264_read_pps(ctx, &gbc, pps);
|
|
||||||
if (err >= 0)
|
|
||||||
err = cbs_h264_replace_pps(ctx, pps);
|
|
||||||
if (err < 0) {
|
|
||||||
av_free(pps);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
pps = unit->content;
|
||||||
|
|
||||||
unit->content = pps;
|
err = cbs_h264_read_pps(ctx, &gbc, pps);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = cbs_h264_replace_pps(ctx, pps);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -763,14 +747,15 @@ static int cbs_h264_read_nal_unit(CodedBitstreamContext *ctx,
|
|||||||
H264RawSlice *slice;
|
H264RawSlice *slice;
|
||||||
int pos, len;
|
int pos, len;
|
||||||
|
|
||||||
slice = av_mallocz(sizeof(*slice));
|
err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*slice),
|
||||||
if (!slice)
|
&cbs_h264_free_slice);
|
||||||
return AVERROR(ENOMEM);
|
if (err < 0)
|
||||||
err = cbs_h264_read_slice_header(ctx, &gbc, &slice->header);
|
return err;
|
||||||
if (err < 0) {
|
slice = unit->content;
|
||||||
av_free(slice);
|
|
||||||
|
err = cbs_h264_read_slice_header(ctx, &gbc, &slice->header);
|
||||||
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
}
|
|
||||||
|
|
||||||
pos = get_bits_count(&gbc);
|
pos = get_bits_count(&gbc);
|
||||||
len = unit->data_size;
|
len = unit->data_size;
|
||||||
@ -783,54 +768,42 @@ static int cbs_h264_read_nal_unit(CodedBitstreamContext *ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
slice->data_size = len - pos / 8;
|
slice->data_size = len - pos / 8;
|
||||||
slice->data = av_malloc(slice->data_size +
|
slice->data_ref = av_buffer_alloc(slice->data_size +
|
||||||
AV_INPUT_BUFFER_PADDING_SIZE);
|
AV_INPUT_BUFFER_PADDING_SIZE);
|
||||||
if (!slice->data) {
|
if (!slice->data_ref)
|
||||||
av_free(slice);
|
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
}
|
slice->data = slice->data_ref->data;
|
||||||
memcpy(slice->data,
|
memcpy(slice->data,
|
||||||
unit->data + pos / 8, slice->data_size);
|
unit->data + pos / 8, slice->data_size);
|
||||||
memset(slice->data + slice->data_size, 0,
|
memset(slice->data + slice->data_size, 0,
|
||||||
AV_INPUT_BUFFER_PADDING_SIZE);
|
AV_INPUT_BUFFER_PADDING_SIZE);
|
||||||
slice->data_bit_start = pos % 8;
|
slice->data_bit_start = pos % 8;
|
||||||
|
|
||||||
unit->content = slice;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case H264_NAL_AUD:
|
case H264_NAL_AUD:
|
||||||
{
|
{
|
||||||
H264RawAUD *aud;
|
err = ff_cbs_alloc_unit_content(ctx, unit,
|
||||||
|
sizeof(H264RawAUD), NULL);
|
||||||
aud = av_mallocz(sizeof(*aud));
|
if (err < 0)
|
||||||
if (!aud)
|
|
||||||
return AVERROR(ENOMEM);
|
|
||||||
err = cbs_h264_read_aud(ctx, &gbc, aud);
|
|
||||||
if (err < 0) {
|
|
||||||
av_free(aud);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
|
||||||
|
|
||||||
unit->content = aud;
|
err = cbs_h264_read_aud(ctx, &gbc, unit->content);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case H264_NAL_SEI:
|
case H264_NAL_SEI:
|
||||||
{
|
{
|
||||||
H264RawSEI *sei;
|
err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(H264RawSEI),
|
||||||
|
&cbs_h264_free_sei);
|
||||||
sei = av_mallocz(sizeof(*sei));
|
if (err < 0)
|
||||||
if (!sei)
|
|
||||||
return AVERROR(ENOMEM);
|
|
||||||
err = cbs_h264_read_sei(ctx, &gbc, sei);
|
|
||||||
if (err < 0) {
|
|
||||||
cbs_h264_free_sei(sei);
|
|
||||||
av_free(sei);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
|
||||||
|
|
||||||
unit->content = sei;
|
err = cbs_h264_read_sei(ctx, &gbc, unit->content);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -856,36 +829,38 @@ static int cbs_h265_read_nal_unit(CodedBitstreamContext *ctx,
|
|||||||
{
|
{
|
||||||
H265RawVPS *vps;
|
H265RawVPS *vps;
|
||||||
|
|
||||||
vps = av_mallocz(sizeof(*vps));
|
err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*vps),
|
||||||
if (!vps)
|
&cbs_h265_free_vps);
|
||||||
return AVERROR(ENOMEM);
|
if (err < 0)
|
||||||
err = cbs_h265_read_vps(ctx, &gbc, vps);
|
|
||||||
if (err >= 0)
|
|
||||||
err = cbs_h265_replace_vps(ctx, vps);
|
|
||||||
if (err < 0) {
|
|
||||||
av_free(vps);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
vps = unit->content;
|
||||||
|
|
||||||
unit->content = vps;
|
err = cbs_h265_read_vps(ctx, &gbc, vps);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = cbs_h265_replace_vps(ctx, vps);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HEVC_NAL_SPS:
|
case HEVC_NAL_SPS:
|
||||||
{
|
{
|
||||||
H265RawSPS *sps;
|
H265RawSPS *sps;
|
||||||
|
|
||||||
sps = av_mallocz(sizeof(*sps));
|
err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*sps),
|
||||||
if (!sps)
|
&cbs_h265_free_sps);
|
||||||
return AVERROR(ENOMEM);
|
if (err < 0)
|
||||||
err = cbs_h265_read_sps(ctx, &gbc, sps);
|
|
||||||
if (err >= 0)
|
|
||||||
err = cbs_h265_replace_sps(ctx, sps);
|
|
||||||
if (err < 0) {
|
|
||||||
av_free(sps);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
sps = unit->content;
|
||||||
|
|
||||||
unit->content = sps;
|
err = cbs_h265_read_sps(ctx, &gbc, sps);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = cbs_h265_replace_sps(ctx, sps);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -893,18 +868,19 @@ static int cbs_h265_read_nal_unit(CodedBitstreamContext *ctx,
|
|||||||
{
|
{
|
||||||
H265RawPPS *pps;
|
H265RawPPS *pps;
|
||||||
|
|
||||||
pps = av_mallocz(sizeof(*pps));
|
err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*pps),
|
||||||
if (!pps)
|
&cbs_h265_free_pps);
|
||||||
return AVERROR(ENOMEM);
|
if (err < 0)
|
||||||
err = cbs_h265_read_pps(ctx, &gbc, pps);
|
|
||||||
if (err >= 0)
|
|
||||||
err = cbs_h265_replace_pps(ctx, pps);
|
|
||||||
if (err < 0) {
|
|
||||||
av_free(pps);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
pps = unit->content;
|
||||||
|
|
||||||
unit->content = pps;
|
err = cbs_h265_read_pps(ctx, &gbc, pps);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = cbs_h265_replace_pps(ctx, pps);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -928,14 +904,15 @@ static int cbs_h265_read_nal_unit(CodedBitstreamContext *ctx,
|
|||||||
H265RawSlice *slice;
|
H265RawSlice *slice;
|
||||||
int pos, len;
|
int pos, len;
|
||||||
|
|
||||||
slice = av_mallocz(sizeof(*slice));
|
err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*slice),
|
||||||
if (!slice)
|
&cbs_h265_free_slice);
|
||||||
return AVERROR(ENOMEM);
|
if (err < 0)
|
||||||
err = cbs_h265_read_slice_segment_header(ctx, &gbc, &slice->header);
|
return err;
|
||||||
if (err < 0) {
|
slice = unit->content;
|
||||||
av_free(slice);
|
|
||||||
|
err = cbs_h265_read_slice_segment_header(ctx, &gbc, &slice->header);
|
||||||
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
}
|
|
||||||
|
|
||||||
pos = get_bits_count(&gbc);
|
pos = get_bits_count(&gbc);
|
||||||
len = unit->data_size;
|
len = unit->data_size;
|
||||||
@ -948,36 +925,29 @@ static int cbs_h265_read_nal_unit(CodedBitstreamContext *ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
slice->data_size = len - pos / 8;
|
slice->data_size = len - pos / 8;
|
||||||
slice->data = av_malloc(slice->data_size +
|
slice->data_ref = av_buffer_alloc(slice->data_size +
|
||||||
AV_INPUT_BUFFER_PADDING_SIZE);
|
AV_INPUT_BUFFER_PADDING_SIZE);
|
||||||
if (!slice->data) {
|
if (!slice->data_ref)
|
||||||
av_free(slice);
|
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
}
|
slice->data = slice->data_ref->data;
|
||||||
memcpy(slice->data,
|
memcpy(slice->data,
|
||||||
unit->data + pos / 8, slice->data_size);
|
unit->data + pos / 8, slice->data_size);
|
||||||
memset(slice->data + slice->data_size, 0,
|
memset(slice->data + slice->data_size, 0,
|
||||||
AV_INPUT_BUFFER_PADDING_SIZE);
|
AV_INPUT_BUFFER_PADDING_SIZE);
|
||||||
slice->data_bit_start = pos % 8;
|
slice->data_bit_start = pos % 8;
|
||||||
|
|
||||||
unit->content = slice;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HEVC_NAL_AUD:
|
case HEVC_NAL_AUD:
|
||||||
{
|
{
|
||||||
H265RawAUD *aud;
|
err = ff_cbs_alloc_unit_content(ctx, unit,
|
||||||
|
sizeof(H265RawAUD), NULL);
|
||||||
aud = av_mallocz(sizeof(*aud));
|
if (err < 0)
|
||||||
if (!aud)
|
|
||||||
return AVERROR(ENOMEM);
|
|
||||||
err = cbs_h265_read_aud(ctx, &gbc, aud);
|
|
||||||
if (err < 0) {
|
|
||||||
av_free(aud);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
|
||||||
|
|
||||||
unit->content = aud;
|
err = cbs_h265_read_aud(ctx, &gbc, unit->content);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1272,7 +1242,7 @@ static int cbs_h2645_write_nal_unit(CodedBitstreamContext *ctx,
|
|||||||
unit->data_size = (put_bits_count(&pbc) + 7) / 8;
|
unit->data_size = (put_bits_count(&pbc) + 7) / 8;
|
||||||
flush_put_bits(&pbc);
|
flush_put_bits(&pbc);
|
||||||
|
|
||||||
err = av_reallocp(&unit->data, unit->data_size);
|
err = ff_cbs_alloc_unit_data(ctx, unit, unit->data_size);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -1354,6 +1324,12 @@ static int cbs_h2645_assemble_fragment(CodedBitstreamContext *ctx,
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
frag->data_ref = av_buffer_create(data, dp, NULL, NULL, 0);
|
||||||
|
if (!frag->data_ref) {
|
||||||
|
av_freep(&data);
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
frag->data = data;
|
frag->data = data;
|
||||||
frag->data_size = dp;
|
frag->data_size = dp;
|
||||||
|
|
||||||
@ -1402,7 +1378,6 @@ const CodedBitstreamType ff_cbs_type_h264 = {
|
|||||||
.write_unit = &cbs_h2645_write_nal_unit,
|
.write_unit = &cbs_h2645_write_nal_unit,
|
||||||
.assemble_fragment = &cbs_h2645_assemble_fragment,
|
.assemble_fragment = &cbs_h2645_assemble_fragment,
|
||||||
|
|
||||||
.free_unit = &cbs_h264_free_nal_unit,
|
|
||||||
.close = &cbs_h264_close,
|
.close = &cbs_h264_close,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1416,6 +1391,5 @@ const CodedBitstreamType ff_cbs_type_h265 = {
|
|||||||
.write_unit = &cbs_h2645_write_nal_unit,
|
.write_unit = &cbs_h2645_write_nal_unit,
|
||||||
.assemble_fragment = &cbs_h2645_assemble_fragment,
|
.assemble_fragment = &cbs_h2645_assemble_fragment,
|
||||||
|
|
||||||
.free_unit = &cbs_h265_free_nal_unit,
|
|
||||||
.close = &cbs_h265_close,
|
.close = &cbs_h265_close,
|
||||||
};
|
};
|
||||||
|
@ -154,6 +154,7 @@ typedef struct H265RawVUI {
|
|||||||
typedef struct H265RawPSExtensionData {
|
typedef struct H265RawPSExtensionData {
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
size_t bit_length;
|
size_t bit_length;
|
||||||
|
AVBufferRef *data_ref;
|
||||||
} H265RawPSExtensionData;
|
} H265RawPSExtensionData;
|
||||||
|
|
||||||
typedef struct H265RawVPS {
|
typedef struct H265RawVPS {
|
||||||
@ -512,6 +513,7 @@ typedef struct H265RawSlice {
|
|||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
size_t data_size;
|
size_t data_size;
|
||||||
int data_bit_start;
|
int data_bit_start;
|
||||||
|
AVBufferRef *data_ref;
|
||||||
} H265RawSlice;
|
} H265RawSlice;
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,9 +53,6 @@ typedef struct CodedBitstreamType {
|
|||||||
int (*assemble_fragment)(CodedBitstreamContext *ctx,
|
int (*assemble_fragment)(CodedBitstreamContext *ctx,
|
||||||
CodedBitstreamFragment *frag);
|
CodedBitstreamFragment *frag);
|
||||||
|
|
||||||
// Free the content and data of a single unit.
|
|
||||||
void (*free_unit)(CodedBitstreamUnit *unit);
|
|
||||||
|
|
||||||
// Free the codec internal state.
|
// Free the codec internal state.
|
||||||
void (*close)(CodedBitstreamContext *ctx);
|
void (*close)(CodedBitstreamContext *ctx);
|
||||||
} CodedBitstreamType;
|
} CodedBitstreamType;
|
||||||
|
@ -102,6 +102,21 @@
|
|||||||
#undef nextbits
|
#undef nextbits
|
||||||
|
|
||||||
|
|
||||||
|
static void cbs_mpeg2_free_user_data(void *unit, uint8_t *content)
|
||||||
|
{
|
||||||
|
MPEG2RawUserData *user = (MPEG2RawUserData*)content;
|
||||||
|
av_buffer_unref(&user->user_data_ref);
|
||||||
|
av_freep(&content);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cbs_mpeg2_free_slice(void *unit, uint8_t *content)
|
||||||
|
{
|
||||||
|
MPEG2RawSlice *slice = (MPEG2RawSlice*)content;
|
||||||
|
av_buffer_unref(&slice->header.extra_information_ref);
|
||||||
|
av_buffer_unref(&slice->data_ref);
|
||||||
|
av_freep(&content);
|
||||||
|
}
|
||||||
|
|
||||||
static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx,
|
static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx,
|
||||||
CodedBitstreamFragment *frag,
|
CodedBitstreamFragment *frag,
|
||||||
int header)
|
int header)
|
||||||
@ -138,7 +153,7 @@ static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx,
|
|||||||
memset(unit_data + unit_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
|
memset(unit_data + unit_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
|
||||||
|
|
||||||
err = ff_cbs_insert_unit_data(ctx, frag, i, unit_type,
|
err = ff_cbs_insert_unit_data(ctx, frag, i, unit_type,
|
||||||
unit_data, unit_size);
|
unit_data, unit_size, NULL);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
av_freep(&unit_data);
|
av_freep(&unit_data);
|
||||||
return err;
|
return err;
|
||||||
@ -168,25 +183,25 @@ static int cbs_mpeg2_read_unit(CodedBitstreamContext *ctx,
|
|||||||
MPEG2RawSlice *slice;
|
MPEG2RawSlice *slice;
|
||||||
int pos, len;
|
int pos, len;
|
||||||
|
|
||||||
slice = av_mallocz(sizeof(*slice));
|
err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*slice),
|
||||||
if (!slice)
|
&cbs_mpeg2_free_slice);
|
||||||
return AVERROR(ENOMEM);
|
if (err < 0)
|
||||||
err = cbs_mpeg2_read_slice_header(ctx, &gbc, &slice->header);
|
return err;
|
||||||
if (err < 0) {
|
slice = unit->content;
|
||||||
av_free(slice);
|
|
||||||
|
err = cbs_mpeg2_read_slice_header(ctx, &gbc, &slice->header);
|
||||||
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
}
|
|
||||||
|
|
||||||
pos = get_bits_count(&gbc);
|
pos = get_bits_count(&gbc);
|
||||||
len = unit->data_size;
|
len = unit->data_size;
|
||||||
|
|
||||||
slice->data_size = len - pos / 8;
|
slice->data_size = len - pos / 8;
|
||||||
slice->data = av_malloc(slice->data_size +
|
slice->data_ref = av_buffer_alloc(slice->data_size +
|
||||||
AV_INPUT_BUFFER_PADDING_SIZE);
|
AV_INPUT_BUFFER_PADDING_SIZE);
|
||||||
if (!slice->data) {
|
if (!slice->data_ref)
|
||||||
av_free(slice);
|
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
}
|
slice->data = slice->data_ref->data;
|
||||||
|
|
||||||
memcpy(slice->data,
|
memcpy(slice->data,
|
||||||
unit->data + pos / 8, slice->data_size);
|
unit->data + pos / 8, slice->data_size);
|
||||||
@ -194,30 +209,29 @@ static int cbs_mpeg2_read_unit(CodedBitstreamContext *ctx,
|
|||||||
AV_INPUT_BUFFER_PADDING_SIZE);
|
AV_INPUT_BUFFER_PADDING_SIZE);
|
||||||
slice->data_bit_start = pos % 8;
|
slice->data_bit_start = pos % 8;
|
||||||
|
|
||||||
unit->content = slice;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
switch (unit->type) {
|
switch (unit->type) {
|
||||||
#define START(start_code, type, func) \
|
#define START(start_code, type, read_func, free_func) \
|
||||||
case start_code: \
|
case start_code: \
|
||||||
{ \
|
{ \
|
||||||
type *header; \
|
type *header; \
|
||||||
header = av_mallocz(sizeof(*header)); \
|
err = ff_cbs_alloc_unit_content(ctx, unit, \
|
||||||
if (!header) \
|
sizeof(*header), free_func); \
|
||||||
return AVERROR(ENOMEM); \
|
if (err < 0) \
|
||||||
err = cbs_mpeg2_read_ ## func(ctx, &gbc, header); \
|
return err; \
|
||||||
if (err < 0) { \
|
header = unit->content; \
|
||||||
av_free(header); \
|
err = cbs_mpeg2_read_ ## read_func(ctx, &gbc, header); \
|
||||||
|
if (err < 0) \
|
||||||
return err; \
|
return err; \
|
||||||
} \
|
|
||||||
unit->content = header; \
|
|
||||||
} \
|
} \
|
||||||
break;
|
break;
|
||||||
START(0x00, MPEG2RawPictureHeader, picture_header);
|
START(0x00, MPEG2RawPictureHeader, picture_header, NULL);
|
||||||
START(0xb2, MPEG2RawUserData, user_data);
|
START(0xb2, MPEG2RawUserData, user_data,
|
||||||
START(0xb3, MPEG2RawSequenceHeader, sequence_header);
|
&cbs_mpeg2_free_user_data);
|
||||||
START(0xb5, MPEG2RawExtensionData, extension_data);
|
START(0xb3, MPEG2RawSequenceHeader, sequence_header, NULL);
|
||||||
START(0xb8, MPEG2RawGroupOfPicturesHeader, group_of_pictures_header);
|
START(0xb5, MPEG2RawExtensionData, extension_data, NULL);
|
||||||
|
START(0xb8, MPEG2RawGroupOfPicturesHeader,
|
||||||
|
group_of_pictures_header, NULL);
|
||||||
#undef START
|
#undef START
|
||||||
default:
|
default:
|
||||||
av_log(ctx->log_ctx, AV_LOG_ERROR, "Unknown start code %02"PRIx32".\n",
|
av_log(ctx->log_ctx, AV_LOG_ERROR, "Unknown start code %02"PRIx32".\n",
|
||||||
@ -335,7 +349,7 @@ static int cbs_mpeg2_write_unit(CodedBitstreamContext *ctx,
|
|||||||
unit->data_size = (put_bits_count(&pbc) + 7) / 8;
|
unit->data_size = (put_bits_count(&pbc) + 7) / 8;
|
||||||
flush_put_bits(&pbc);
|
flush_put_bits(&pbc);
|
||||||
|
|
||||||
err = av_reallocp(&unit->data, unit->data_size);
|
err = ff_cbs_alloc_unit_data(ctx, unit, unit->data_size);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -355,9 +369,10 @@ static int cbs_mpeg2_assemble_fragment(CodedBitstreamContext *ctx,
|
|||||||
for (i = 0; i < frag->nb_units; i++)
|
for (i = 0; i < frag->nb_units; i++)
|
||||||
size += 3 + frag->units[i].data_size;
|
size += 3 + frag->units[i].data_size;
|
||||||
|
|
||||||
data = av_malloc(size);
|
frag->data_ref = av_buffer_alloc(size);
|
||||||
if (!data)
|
if (!frag->data_ref)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
|
data = frag->data_ref->data;
|
||||||
|
|
||||||
dp = 0;
|
dp = 0;
|
||||||
for (i = 0; i < frag->nb_units; i++) {
|
for (i = 0; i < frag->nb_units; i++) {
|
||||||
@ -379,19 +394,6 @@ static int cbs_mpeg2_assemble_fragment(CodedBitstreamContext *ctx,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cbs_mpeg2_free_unit(CodedBitstreamUnit *unit)
|
|
||||||
{
|
|
||||||
if (MPEG2_START_IS_SLICE(unit->type)) {
|
|
||||||
MPEG2RawSlice *slice = unit->content;
|
|
||||||
av_freep(&slice->data);
|
|
||||||
av_freep(&slice->header.extra_information);
|
|
||||||
} else if (unit->type == MPEG2_START_USER_DATA) {
|
|
||||||
MPEG2RawUserData *user = unit->content;
|
|
||||||
av_freep(&user->user_data);
|
|
||||||
}
|
|
||||||
av_freep(&unit->content);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cbs_mpeg2_close(CodedBitstreamContext *ctx)
|
static void cbs_mpeg2_close(CodedBitstreamContext *ctx)
|
||||||
{
|
{
|
||||||
CodedBitstreamMPEG2Context *priv = ctx->priv_data;
|
CodedBitstreamMPEG2Context *priv = ctx->priv_data;
|
||||||
@ -409,6 +411,5 @@ const CodedBitstreamType ff_cbs_type_mpeg2 = {
|
|||||||
.write_unit = &cbs_mpeg2_write_unit,
|
.write_unit = &cbs_mpeg2_write_unit,
|
||||||
.assemble_fragment = &cbs_mpeg2_assemble_fragment,
|
.assemble_fragment = &cbs_mpeg2_assemble_fragment,
|
||||||
|
|
||||||
.free_unit = &cbs_mpeg2_free_unit,
|
|
||||||
.close = &cbs_mpeg2_close,
|
.close = &cbs_mpeg2_close,
|
||||||
};
|
};
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "libavutil/buffer.h"
|
||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
MPEG2_START_PICTURE = 0x00,
|
MPEG2_START_PICTURE = 0x00,
|
||||||
@ -76,6 +78,7 @@ typedef struct MPEG2RawUserData {
|
|||||||
|
|
||||||
uint8_t *user_data;
|
uint8_t *user_data;
|
||||||
size_t user_data_length;
|
size_t user_data_length;
|
||||||
|
AVBufferRef *user_data_ref;
|
||||||
} MPEG2RawUserData;
|
} MPEG2RawUserData;
|
||||||
|
|
||||||
typedef struct MPEG2RawSequenceExtension {
|
typedef struct MPEG2RawSequenceExtension {
|
||||||
@ -195,6 +198,7 @@ typedef struct MPEG2RawSliceHeader {
|
|||||||
|
|
||||||
size_t extra_information_length;
|
size_t extra_information_length;
|
||||||
uint8_t *extra_information;
|
uint8_t *extra_information;
|
||||||
|
AVBufferRef *extra_information_ref;
|
||||||
} MPEG2RawSliceHeader;
|
} MPEG2RawSliceHeader;
|
||||||
|
|
||||||
typedef struct MPEG2RawSlice {
|
typedef struct MPEG2RawSlice {
|
||||||
@ -203,6 +207,7 @@ typedef struct MPEG2RawSlice {
|
|||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
size_t data_size;
|
size_t data_size;
|
||||||
int data_bit_start;
|
int data_bit_start;
|
||||||
|
AVBufferRef *data_ref;
|
||||||
} MPEG2RawSlice;
|
} MPEG2RawSlice;
|
||||||
|
|
||||||
|
|
||||||
|
@ -71,9 +71,10 @@ static int FUNC(user_data)(CodedBitstreamContext *ctx, RWContext *rw,
|
|||||||
av_assert0(k % 8 == 0);
|
av_assert0(k % 8 == 0);
|
||||||
current->user_data_length = k /= 8;
|
current->user_data_length = k /= 8;
|
||||||
if (k > 0) {
|
if (k > 0) {
|
||||||
current->user_data = av_malloc(k);
|
current->user_data_ref = av_buffer_alloc(k);
|
||||||
if (!current->user_data)
|
if (!current->user_data_ref)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
|
current->user_data = current->user_data_ref->data;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -271,7 +271,7 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out)
|
|||||||
aud->primary_pic_type = j;
|
aud->primary_pic_type = j;
|
||||||
|
|
||||||
err = ff_cbs_insert_unit_content(ctx->cbc, au,
|
err = ff_cbs_insert_unit_content(ctx->cbc, au,
|
||||||
0, H264_NAL_AUD, aud);
|
0, H264_NAL_AUD, aud, NULL);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
av_log(bsf, AV_LOG_ERROR, "Failed to insert AUD.\n");
|
av_log(bsf, AV_LOG_ERROR, "Failed to insert AUD.\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -318,8 +318,8 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket *out)
|
|||||||
|
|
||||||
sei->nal_unit_header.nal_unit_type = H264_NAL_SEI;
|
sei->nal_unit_header.nal_unit_type = H264_NAL_SEI;
|
||||||
|
|
||||||
err = ff_cbs_insert_unit_content(ctx->cbc, au,
|
err = ff_cbs_insert_unit_content(ctx->cbc, au, sei_pos,
|
||||||
sei_pos, H264_NAL_SEI, sei);
|
H264_NAL_SEI, sei, NULL);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
av_log(bsf, AV_LOG_ERROR, "Failed to insert SEI.\n");
|
av_log(bsf, AV_LOG_ERROR, "Failed to insert SEI.\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -289,7 +289,7 @@ static int h265_metadata_filter(AVBSFContext *bsf, AVPacket *out)
|
|||||||
aud->pic_type = pic_type;
|
aud->pic_type = pic_type;
|
||||||
|
|
||||||
err = ff_cbs_insert_unit_content(ctx->cbc, au,
|
err = ff_cbs_insert_unit_content(ctx->cbc, au,
|
||||||
0, HEVC_NAL_AUD, aud);
|
0, HEVC_NAL_AUD, aud, NULL);
|
||||||
if (err) {
|
if (err) {
|
||||||
av_log(bsf, AV_LOG_ERROR, "Failed to insert AUD.\n");
|
av_log(bsf, AV_LOG_ERROR, "Failed to insert AUD.\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -167,7 +167,8 @@ static int mpeg2_metadata_update_fragment(AVBSFContext *bsf,
|
|||||||
|
|
||||||
err = ff_cbs_insert_unit_content(ctx->cbc, frag, se_pos + 1,
|
err = ff_cbs_insert_unit_content(ctx->cbc, frag, se_pos + 1,
|
||||||
MPEG2_START_EXTENSION,
|
MPEG2_START_EXTENSION,
|
||||||
&ctx->sequence_display_extension);
|
&ctx->sequence_display_extension,
|
||||||
|
NULL);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
av_log(bsf, AV_LOG_ERROR, "Failed to insert new sequence "
|
av_log(bsf, AV_LOG_ERROR, "Failed to insert new sequence "
|
||||||
"display extension.\n");
|
"display extension.\n");
|
||||||
|
@ -135,7 +135,7 @@ static int vaapi_encode_h264_add_nal(AVCodecContext *avctx,
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = ff_cbs_insert_unit_content(priv->cbc, au, -1,
|
err = ff_cbs_insert_unit_content(priv->cbc, au, -1,
|
||||||
header->nal_unit_type, nal_unit);
|
header->nal_unit_type, nal_unit, NULL);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
av_log(avctx, AV_LOG_ERROR, "Failed to add NAL unit: "
|
av_log(avctx, AV_LOG_ERROR, "Failed to add NAL unit: "
|
||||||
"type = %d.\n", header->nal_unit_type);
|
"type = %d.\n", header->nal_unit_type);
|
||||||
|
@ -105,7 +105,7 @@ static int vaapi_encode_h265_add_nal(AVCodecContext *avctx,
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = ff_cbs_insert_unit_content(priv->cbc, au, -1,
|
err = ff_cbs_insert_unit_content(priv->cbc, au, -1,
|
||||||
header->nal_unit_type, nal_unit);
|
header->nal_unit_type, nal_unit, NULL);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
av_log(avctx, AV_LOG_ERROR, "Failed to add NAL unit: "
|
av_log(avctx, AV_LOG_ERROR, "Failed to add NAL unit: "
|
||||||
"type = %d.\n", header->nal_unit_type);
|
"type = %d.\n", header->nal_unit_type);
|
||||||
|
@ -92,7 +92,7 @@ static int vaapi_encode_mpeg2_add_header(AVCodecContext *avctx,
|
|||||||
VAAPIEncodeMPEG2Context *priv = ctx->priv_data;
|
VAAPIEncodeMPEG2Context *priv = ctx->priv_data;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = ff_cbs_insert_unit_content(priv->cbc, frag, -1, type, header);
|
err = ff_cbs_insert_unit_content(priv->cbc, frag, -1, type, header, NULL);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
av_log(avctx, AV_LOG_ERROR, "Failed to add header: "
|
av_log(avctx, AV_LOG_ERROR, "Failed to add header: "
|
||||||
"type = %d.\n", type);
|
"type = %d.\n", type);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user