You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-10 06:10:52 +02:00
cbs: Describe allocate/free methods in tabular form
Unit types are split into three categories, depending on how their content is managed: * POD structure - these require no special treatment. * Structure containing references to refcounted buffers - these can use a common free function when the offsets of all the internal references are known. * More complex structures - these still require ad-hoc treatment. For each codec we can then maintain a table of descriptors for each set of equivalent unit types, defining the mechanism needed to allocate/free that unit content. This is not required to be used immediately - a new alloc function supports this, but does not replace the old one which works without referring to these tables.
This commit is contained in:
@@ -802,3 +802,72 @@ void ff_cbs_delete_unit(CodedBitstreamFragment *frag,
|
|||||||
frag->units + position + 1,
|
frag->units + position + 1,
|
||||||
(frag->nb_units - position) * sizeof(*frag->units));
|
(frag->nb_units - position) * sizeof(*frag->units));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cbs_default_free_unit_content(void *opaque, uint8_t *data)
|
||||||
|
{
|
||||||
|
const CodedBitstreamUnitTypeDescriptor *desc = opaque;
|
||||||
|
if (desc->content_type == CBS_CONTENT_TYPE_INTERNAL_REFS) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < desc->nb_ref_offsets; i++) {
|
||||||
|
void **ptr = (void**)(data + desc->ref_offsets[i]);
|
||||||
|
av_buffer_unref((AVBufferRef**)(ptr + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
av_free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const CodedBitstreamUnitTypeDescriptor
|
||||||
|
*cbs_find_unit_type_desc(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamUnit *unit)
|
||||||
|
{
|
||||||
|
const CodedBitstreamUnitTypeDescriptor *desc;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
if (!ctx->codec->unit_types)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0;; i++) {
|
||||||
|
desc = &ctx->codec->unit_types[i];
|
||||||
|
if (desc->nb_unit_types == 0)
|
||||||
|
break;
|
||||||
|
if (desc->nb_unit_types == CBS_UNIT_TYPE_RANGE) {
|
||||||
|
if (unit->type >= desc->unit_type_range_start &&
|
||||||
|
unit->type <= desc->unit_type_range_end)
|
||||||
|
return desc;
|
||||||
|
} else {
|
||||||
|
for (j = 0; j < desc->nb_unit_types; j++) {
|
||||||
|
if (desc->unit_types[j] == unit->type)
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ff_cbs_alloc_unit_content2(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamUnit *unit)
|
||||||
|
{
|
||||||
|
const CodedBitstreamUnitTypeDescriptor *desc;
|
||||||
|
|
||||||
|
av_assert0(!unit->content && !unit->content_ref);
|
||||||
|
|
||||||
|
desc = cbs_find_unit_type_desc(ctx, unit);
|
||||||
|
if (!desc)
|
||||||
|
return AVERROR(ENOSYS);
|
||||||
|
|
||||||
|
unit->content = av_mallocz(desc->content_size);
|
||||||
|
if (!unit->content)
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
|
||||||
|
unit->content_ref =
|
||||||
|
av_buffer_create(unit->content, desc->content_size,
|
||||||
|
desc->content_free ? desc->content_free
|
||||||
|
: cbs_default_free_unit_content,
|
||||||
|
(void*)desc, 0);
|
||||||
|
if (!unit->content_ref) {
|
||||||
|
av_freep(&unit->content);
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -349,6 +349,15 @@ int ff_cbs_alloc_unit_content(CodedBitstreamUnit *unit,
|
|||||||
size_t size,
|
size_t size,
|
||||||
void (*free)(void *opaque, uint8_t *content));
|
void (*free)(void *opaque, uint8_t *content));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate a new internal content buffer matching the type of the unit.
|
||||||
|
*
|
||||||
|
* The content will be zeroed.
|
||||||
|
*/
|
||||||
|
int ff_cbs_alloc_unit_content2(CodedBitstreamContext *ctx,
|
||||||
|
CodedBitstreamUnit *unit);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate a new internal data buffer of the given size in the unit.
|
* Allocate a new internal data buffer of the given size in the unit.
|
||||||
*
|
*
|
||||||
|
@@ -25,11 +25,72 @@
|
|||||||
#include "put_bits.h"
|
#include "put_bits.h"
|
||||||
|
|
||||||
|
|
||||||
|
enum CBSContentType {
|
||||||
|
// Unit content is a simple structure.
|
||||||
|
CBS_CONTENT_TYPE_POD,
|
||||||
|
// Unit content contains some references to other structures, but all
|
||||||
|
// managed via buffer reference counting. The descriptor defines the
|
||||||
|
// structure offsets of every buffer reference.
|
||||||
|
CBS_CONTENT_TYPE_INTERNAL_REFS,
|
||||||
|
// Unit content is something more complex. The descriptor defines
|
||||||
|
// special functions to manage the content.
|
||||||
|
CBS_CONTENT_TYPE_COMPLEX,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
// Maximum number of unit types described by the same unit type
|
||||||
|
// descriptor.
|
||||||
|
CBS_MAX_UNIT_TYPES = 3,
|
||||||
|
// Maximum number of reference buffer offsets in any one unit.
|
||||||
|
CBS_MAX_REF_OFFSETS = 2,
|
||||||
|
// Special value used in a unit type descriptor to indicate that it
|
||||||
|
// applies to a large range of types rather than a set of discrete
|
||||||
|
// values.
|
||||||
|
CBS_UNIT_TYPE_RANGE = -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef const struct CodedBitstreamUnitTypeDescriptor {
|
||||||
|
// Number of entries in the unit_types array, or the special value
|
||||||
|
// CBS_UNIT_TYPE_RANGE to indicate that the range fields should be
|
||||||
|
// used instead.
|
||||||
|
int nb_unit_types;
|
||||||
|
|
||||||
|
// Array of unit types that this entry describes.
|
||||||
|
const CodedBitstreamUnitType unit_types[CBS_MAX_UNIT_TYPES];
|
||||||
|
|
||||||
|
// Start and end of unit type range, used if nb_unit_types is
|
||||||
|
// CBS_UNIT_TYPE_RANGE.
|
||||||
|
const CodedBitstreamUnitType unit_type_range_start;
|
||||||
|
const CodedBitstreamUnitType unit_type_range_end;
|
||||||
|
|
||||||
|
// The type of content described.
|
||||||
|
enum CBSContentType content_type;
|
||||||
|
// The size of the structure which should be allocated to contain
|
||||||
|
// the decomposed content of this type of unit.
|
||||||
|
size_t content_size;
|
||||||
|
|
||||||
|
// Number of entries in the ref_offsets array. Only used if the
|
||||||
|
// content_type is CBS_CONTENT_TYPE_INTERNAL_REFS.
|
||||||
|
int nb_ref_offsets;
|
||||||
|
// The structure must contain two adjacent elements:
|
||||||
|
// type *field;
|
||||||
|
// AVBufferRef *field_ref;
|
||||||
|
// where field points to something in the buffer referred to by
|
||||||
|
// field_ref. This offset is then set to offsetof(struct, field).
|
||||||
|
size_t ref_offsets[CBS_MAX_REF_OFFSETS];
|
||||||
|
|
||||||
|
void (*content_free)(void *opaque, uint8_t *data);
|
||||||
|
} CodedBitstreamUnitTypeDescriptor;
|
||||||
|
|
||||||
typedef struct CodedBitstreamType {
|
typedef struct CodedBitstreamType {
|
||||||
enum AVCodecID codec_id;
|
enum AVCodecID codec_id;
|
||||||
|
|
||||||
size_t priv_data_size;
|
size_t priv_data_size;
|
||||||
|
|
||||||
|
// List of unit type descriptors for this codec.
|
||||||
|
// Terminated by a descriptor with nb_unit_types equal to zero.
|
||||||
|
const CodedBitstreamUnitTypeDescriptor *unit_types;
|
||||||
|
|
||||||
// Split frag->data into coded bitstream units, creating the
|
// Split frag->data into coded bitstream units, creating the
|
||||||
// frag->units array. Fill data but not content on each unit.
|
// frag->units array. Fill data but not content on each unit.
|
||||||
// The header argument should be set if the fragment came from
|
// The header argument should be set if the fragment came from
|
||||||
|
Reference in New Issue
Block a user