[FFmpeg-devel] [PATCH 2/7] cbs: Describe allocate/free methods in tabular form
Mark Thompson
sw at jkqxz.net
Thu Jan 24 01:01:09 EET 2019
Unit types are split into three categories, depending on how their
content is managed:
* POD structure - these require no special treatment.
* Structure containing direct internal references to other structures -
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 unit
type, 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.
---
libavcodec/cbs.c | 59 +++++++++++++++++++++++++++++++++++++++
libavcodec/cbs.h | 16 +++++++++++
libavcodec/cbs_internal.h | 31 ++++++++++++++++++++
3 files changed, 106 insertions(+)
diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c
index ecbf57c293..deabf5dde5 100644
--- a/libavcodec/cbs.c
+++ b/libavcodec/cbs.c
@@ -665,3 +665,62 @@ int ff_cbs_delete_unit(CodedBitstreamContext *ctx,
return 0;
}
+
+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++)
+ av_buffer_unref((AVBufferRef**)(data + desc->ref_offsets[i]));
+ }
+ av_free(data);
+}
+
+static const CodedBitstreamUnitTypeDescriptor
+ *cbs_find_unit_type_desc(CodedBitstreamContext *ctx,
+ CodedBitstreamUnit *unit)
+{
+ const CodedBitstreamUnitTypeDescriptor *desc;
+ int i;
+
+ if (!ctx->codec->unit_types)
+ return NULL;
+
+ for (i = 0;; i++) {
+ desc = &ctx->codec->unit_types[i];
+ if (desc->unit_type == CBS_INVALID_UNIT_TYPE)
+ break;
+ if (desc->unit_type == 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;
+}
diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h
index 053eccffde..1079f625bf 100644
--- a/libavcodec/cbs.h
+++ b/libavcodec/cbs.h
@@ -54,6 +54,13 @@ struct CodedBitstreamType;
*/
typedef uint32_t CodedBitstreamUnitType;
+/**
+ * Value which is never valid as a unit type.
+ *
+ * This can be used as a sentinel.
+ */
+#define CBS_INVALID_UNIT_TYPE (UINT32_MAX)
+
/**
* Coded bitstream unit structure.
*
@@ -312,6 +319,15 @@ int ff_cbs_alloc_unit_content(CodedBitstreamContext *ctx,
size_t size,
void (*free)(void *unit, 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.
*
diff --git a/libavcodec/cbs_internal.h b/libavcodec/cbs_internal.h
index 53f2e5d187..667c90cb14 100644
--- a/libavcodec/cbs_internal.h
+++ b/libavcodec/cbs_internal.h
@@ -25,11 +25,42 @@
#include "put_bits.h"
+enum {
+ // 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 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,
+};
+
+// Maximum number of reference buffer offsets in any one unit.
+#define CBS_MAX_REF_OFFSETS 1
+
+typedef struct CodedBitstreamUnitTypeDescriptor {
+ CodedBitstreamUnitType unit_type;
+
+ int content_type;
+ size_t content_size;
+
+ int nb_ref_offsets;
+ size_t ref_offsets[CBS_MAX_REF_OFFSETS];
+
+ void (*content_free)(void *opaque, uint8_t *data);
+} CodedBitstreamUnitTypeDescriptor;
+
typedef struct CodedBitstreamType {
enum AVCodecID codec_id;
size_t priv_data_size;
+ // List of unit type descriptors for this codec.
+ // Terminated by a descriptor with type CBS_INVALID_UNIT_TYPE.
+ const CodedBitstreamUnitTypeDescriptor *unit_types;
+
// Split frag->data into coded bitstream units, creating the
// frag->units array. Fill data but not content on each unit.
// The header argument should be set if the fragment came from
--
2.19.2
More information about the ffmpeg-devel
mailing list