[FFmpeg-devel,2/5] cbs: Add a macro to create functions for deep copying

Submitted by Andreas Rheinhardt on Nov. 26, 2018, 1:39 p.m.

Details

Message ID 20181126133913.2356-2-andreas.rheinhardt@googlemail.com
State New
Headers show

Commit Message

Andreas Rheinhardt Nov. 26, 2018, 1:39 p.m.
Some structs in cbs (most importantly some of the parameter sets of
H.264/HEVC) can contain external buffers so that shallow copies are not
enough for them; furthermore, they need a special free-callback
function. The macro provided in this commit can be used to easily create
functions both for copying as well as freeing such structures.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@googlemail.com>
---
 libavcodec/cbs_internal.h | 53 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

Patch hide | download patch | download mbox

diff --git a/libavcodec/cbs_internal.h b/libavcodec/cbs_internal.h
index 62a836af90..dd45748c61 100644
--- a/libavcodec/cbs_internal.h
+++ b/libavcodec/cbs_internal.h
@@ -98,4 +98,57 @@  extern const CodedBitstreamType ff_cbs_type_mpeg2;
 extern const CodedBitstreamType ff_cbs_type_vp9;
 
 
+enum {
+    BITS,
+    BYTES
+};
+
+// The following macro automatically creates both (deep) copy and
+// free functions for structs with exactly one internal buffer.
+
+#define cbs_copy_free(codec, type, var, buffer, size_element, size_offset, size_unit) \
+static void cbs_ ## codec ## _free_ ## var(void *unit, uint8_t *content) \
+{ \
+    type *var = (type *)content; \
+ \
+    av_buffer_unref(&var->buffer ## _ref); \
+    av_freep(&var); \
+} \
+ \
+static AVBufferRef *cbs_ ## codec ## _copy_ ## var(const type *source) \
+{ \
+    AVBufferRef *copy_ref; \
+    type *copy; \
+ \
+    copy = av_malloc(sizeof(type)); \
+    if (!copy) \
+        return NULL; \
+    memcpy(copy, source, sizeof(type)); \
+ \
+    copy_ref = av_buffer_create((uint8_t*)copy, sizeof(type), \
+                            &cbs_ ## codec ## _free_ ## var, \
+                            NULL, 0); \
+    if (!copy_ref) { \
+        av_free(copy); \
+        return NULL; \
+    } \
+ \
+    if (source->buffer) { \
+        size_t size = (size_t)source->size_element + size_offset; \
+        if (size_unit == BITS) \
+            size = (size + 7) / 8; \
+ \
+        copy->buffer ## _ref = av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE); \
+        if (!copy->buffer ## _ref) {\
+            av_buffer_unref(&copy_ref); \
+            return NULL; \
+        } \
+        copy->buffer = copy->buffer ## _ref->data; \
+        memcpy(copy->buffer, source->buffer, size); \
+        memset(copy->buffer + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); \
+    } \
+ \
+    return copy_ref; \
+}
+
 #endif /* AVCODEC_CBS_INTERNAL_H */