aboutsummaryrefslogtreecommitdiffstats
path: root/libavcodec/cbs.c
diff options
context:
space:
mode:
authorAndreas Rheinhardt <andreas.rheinhardt@outlook.com>2022-08-04 11:59:16 +0200
committerAndreas Rheinhardt <andreas.rheinhardt@outlook.com>2023-10-07 22:35:05 +0200
commit3e9b8d14e5d0df72765a1c9ca683c9d0f1d51e1a (patch)
treefd1b7cbc5358212171beb26f98e21cc0bf02216e /libavcodec/cbs.c
parent56dd585146288070c98a9429ae85dc3551940a4b (diff)
downloadffmpeg-3e9b8d14e5d0df72765a1c9ca683c9d0f1d51e1a.tar.gz
avcodec/cbs: Use RefStruct-API for unit content
This avoids allocations and error checks etc. as well as duplicate pointer lists in the CodedBitstreamFooContexts. It also avoids casting const away for use as opaque, as the RefStruct API supports const opaques. The fact that some of the units are not refcounted (i.e. they are sometimes part of an encoding context like VAAPIEncodeH264Context) meant that CodedBitstreamUnit still contains two pointers, one to the content and another ownership pointer, replacing the AVBufferRef* pointer. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Diffstat (limited to 'libavcodec/cbs.c')
-rw-r--r--libavcodec/cbs.c101
1 files changed, 45 insertions, 56 deletions
diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c
index daf7f66427..cdd7adebeb 100644
--- a/libavcodec/cbs.c
+++ b/libavcodec/cbs.c
@@ -28,6 +28,7 @@
#include "avcodec.h"
#include "cbs.h"
#include "cbs_internal.h"
+#include "refstruct.h"
static const CodedBitstreamType *const cbs_type_table[] = {
@@ -152,7 +153,7 @@ av_cold void ff_cbs_close(CodedBitstreamContext **ctx_ptr)
static void cbs_unit_uninit(CodedBitstreamUnit *unit)
{
- av_buffer_unref(&unit->content_ref);
+ ff_refstruct_unref(&unit->content_ref);
unit->content = NULL;
av_buffer_unref(&unit->data_ref);
@@ -200,7 +201,7 @@ static int cbs_read_fragment_content(CodedBitstreamContext *ctx,
continue;
}
- av_buffer_unref(&unit->content_ref);
+ ff_refstruct_unref(&unit->content_ref);
unit->content = NULL;
av_assert0(unit->data && unit->data_ref);
@@ -214,7 +215,7 @@ static int cbs_read_fragment_content(CodedBitstreamContext *ctx,
av_log(ctx->log_ctx, AV_LOG_VERBOSE,
"Skipping decomposition of unit %d "
"(type %"PRIu32").\n", i, unit->type);
- av_buffer_unref(&unit->content_ref);
+ ff_refstruct_unref(&unit->content_ref);
unit->content = NULL;
} else if (err < 0) {
av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to read unit %d "
@@ -776,28 +777,22 @@ int ff_cbs_insert_unit_content(CodedBitstreamFragment *frag,
int position,
CodedBitstreamUnitType type,
void *content,
- AVBufferRef *content_buf)
+ void *content_ref)
{
CodedBitstreamUnit *unit;
- AVBufferRef *content_ref;
int err;
if (position == -1)
position = frag->nb_units;
av_assert0(position >= 0 && position <= frag->nb_units);
- if (content_buf) {
- content_ref = av_buffer_ref(content_buf);
- if (!content_ref)
- return AVERROR(ENOMEM);
- } else {
- content_ref = NULL;
- }
-
err = cbs_insert_unit(frag, position);
- if (err < 0) {
- av_buffer_unref(&content_ref);
+ if (err < 0)
return err;
+
+ if (content_ref) {
+ // Create our own reference out of the user-supplied one.
+ content_ref = ff_refstruct_ref(content_ref);
}
unit = &frag->units[position];
@@ -871,15 +866,14 @@ void ff_cbs_delete_unit(CodedBitstreamFragment *frag,
(frag->nb_units - position) * sizeof(*frag->units));
}
-static void cbs_default_free_unit_content(void *opaque, uint8_t *data)
+static void cbs_default_free_unit_content(FFRefStructOpaque opaque, void *content)
{
- const CodedBitstreamUnitTypeDescriptor *desc = opaque;
+ const CodedBitstreamUnitTypeDescriptor *desc = opaque.c;
for (int i = 0; i < desc->type.ref.nb_offsets; i++) {
- void **ptr = (void**)(data + desc->type.ref.offsets[i]);
+ void **ptr = (void**)((char*)content + desc->type.ref.offsets[i]);
av_buffer_unref((AVBufferRef**)(ptr + 1));
}
- av_free(data);
}
static const CodedBitstreamUnitTypeDescriptor
@@ -910,6 +904,15 @@ static const CodedBitstreamUnitTypeDescriptor
return NULL;
}
+static void *cbs_alloc_content(const CodedBitstreamUnitTypeDescriptor *desc)
+{
+ return ff_refstruct_alloc_ext_c(desc->content_size, 0,
+ (FFRefStructOpaque){ .c = desc },
+ desc->content_type == CBS_CONTENT_TYPE_COMPLEX
+ ? desc->type.complex.content_free
+ : cbs_default_free_unit_content);
+}
+
int ff_cbs_alloc_unit_content(CodedBitstreamContext *ctx,
CodedBitstreamUnit *unit)
{
@@ -921,27 +924,17 @@ int ff_cbs_alloc_unit_content(CodedBitstreamContext *ctx,
if (!desc)
return AVERROR(ENOSYS);
- unit->content = av_mallocz(desc->content_size);
- if (!unit->content)
+ unit->content_ref = cbs_alloc_content(desc);
+ if (!unit->content_ref)
return AVERROR(ENOMEM);
-
- unit->content_ref =
- av_buffer_create(unit->content, desc->content_size,
- desc->content_type == CBS_CONTENT_TYPE_COMPLEX
- ? desc->type.complex.content_free
- : cbs_default_free_unit_content,
- (void*)desc, 0);
- if (!unit->content_ref) {
- av_freep(&unit->content);
- return AVERROR(ENOMEM);
- }
+ unit->content = unit->content_ref;
return 0;
}
-static int cbs_clone_internal_refs_unit_content(AVBufferRef **clone_ref,
- const CodedBitstreamUnit *unit,
- const CodedBitstreamUnitTypeDescriptor *desc)
+static int cbs_clone_noncomplex_unit_content(void **clonep,
+ const CodedBitstreamUnit *unit,
+ const CodedBitstreamUnitTypeDescriptor *desc)
{
const uint8_t *src;
uint8_t *copy;
@@ -950,9 +943,15 @@ static int cbs_clone_internal_refs_unit_content(AVBufferRef **clone_ref,
av_assert0(unit->content);
src = unit->content;
- copy = av_memdup(src, desc->content_size);
+ copy = cbs_alloc_content(desc);
if (!copy)
return AVERROR(ENOMEM);
+ memcpy(copy, src, desc->content_size);
+ for (int i = 0; i < desc->type.ref.nb_offsets; i++) {
+ void **ptr = (void**)(copy + desc->type.ref.offsets[i]);
+ /* Zero all the AVBufferRefs as they are owned by src. */
+ *(ptr + 1) = NULL;
+ }
for (i = 0; i < desc->type.ref.nb_offsets; i++) {
const uint8_t *const *src_ptr = (const uint8_t* const*)(src + desc->type.ref.offsets[i]);
@@ -978,22 +977,12 @@ static int cbs_clone_internal_refs_unit_content(AVBufferRef **clone_ref,
goto fail;
}
}
-
- *clone_ref = av_buffer_create(copy, desc->content_size,
- cbs_default_free_unit_content,
- (void*)desc, 0);
- if (!*clone_ref) {
- err = AVERROR(ENOMEM);
- goto fail;
- }
+ *clonep = copy;
return 0;
fail:
- for (--i; i >= 0; i--)
- av_buffer_unref((AVBufferRef**)(copy + desc->type.ref.offsets[i]));
- av_freep(&copy);
- *clone_ref = NULL;
+ ff_refstruct_unref(&copy);
return err;
}
@@ -1006,7 +995,7 @@ static int cbs_clone_unit_content(CodedBitstreamContext *ctx,
CodedBitstreamUnit *unit)
{
const CodedBitstreamUnitTypeDescriptor *desc;
- AVBufferRef *ref;
+ void *new_content;
int err;
desc = cbs_find_unit_type_desc(ctx, unit);
@@ -1015,13 +1004,13 @@ static int cbs_clone_unit_content(CodedBitstreamContext *ctx,
switch (desc->content_type) {
case CBS_CONTENT_TYPE_INTERNAL_REFS:
- err = cbs_clone_internal_refs_unit_content(&ref, unit, desc);
+ err = cbs_clone_noncomplex_unit_content(&new_content, unit, desc);
break;
case CBS_CONTENT_TYPE_COMPLEX:
if (!desc->type.complex.content_clone)
return AVERROR_PATCHWELCOME;
- err = desc->type.complex.content_clone(&ref, unit);
+ err = desc->type.complex.content_clone(&new_content, unit);
break;
default:
@@ -1031,8 +1020,8 @@ static int cbs_clone_unit_content(CodedBitstreamContext *ctx,
if (err < 0)
return err;
- unit->content_ref = ref;
- unit->content = ref->data;
+ unit->content_ref = new_content;
+ unit->content = new_content;
return 0;
}
@@ -1048,17 +1037,17 @@ int ff_cbs_make_unit_refcounted(CodedBitstreamContext *ctx,
int ff_cbs_make_unit_writable(CodedBitstreamContext *ctx,
CodedBitstreamUnit *unit)
{
- AVBufferRef *ref = unit->content_ref;
+ void *ref = unit->content_ref;
int err;
av_assert0(unit->content);
- if (ref && av_buffer_is_writable(ref))
+ if (ref && ff_refstruct_exclusive(ref))
return 0;
err = cbs_clone_unit_content(ctx, unit);
if (err < 0)
return err;
- av_buffer_unref(&ref);
+ ff_refstruct_unref(&ref);
return 0;
}