summaryrefslogtreecommitdiff
path: root/libavcodec/cbs.c
diff options
context:
space:
mode:
authorMark Thompson <sw@jkqxz.net>2020-07-27 17:32:18 +0100
committerMark Thompson <sw@jkqxz.net>2020-09-02 00:00:57 +0100
commitbc7a7e0d65bd72b317b2c4b84fac505ba3db7556 (patch)
tree888843bef0e087fa2a0725649b0dcd337ec5bc85 /libavcodec/cbs.c
parent1fe77d4a637c4033180a35b6ebf13b5a4707d2a4 (diff)
downloadffmpeg-bc7a7e0d65bd72b317b2c4b84fac505ba3db7556.tar.gz
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.
Diffstat (limited to 'libavcodec/cbs.c')
-rw-r--r--libavcodec/cbs.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c
index 6464980c8e..61cf8e3466 100644
--- a/libavcodec/cbs.c
+++ b/libavcodec/cbs.c
@@ -802,3 +802,72 @@ void ff_cbs_delete_unit(CodedBitstreamFragment *frag,
frag->units + position + 1,
(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;
+}