[FFmpeg-devel] [PATCH 2/6] cbs_h2645: Do a deep copy for parameter sets

Andreas Rheinhardt andreas.rheinhardt at googlemail.com
Fri Nov 9 07:31:34 EET 2018


This commit solves dangling pointers problems when the content of a
parameter set isn't refcounted in the beginning: Now a deep copy of the
parameter sets is performed.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at googlemail.com>
---
 libavcodec/cbs_h2645.c | 59 +++++++++++++++++++++++++++++++++++-------
 1 file changed, 50 insertions(+), 9 deletions(-)

diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c
index 37b0207420..e73706f2e6 100644
--- a/libavcodec/cbs_h2645.c
+++ b/libavcodec/cbs_h2645.c
@@ -674,7 +674,26 @@ static int cbs_h2645_split_fragment(CodedBitstreamContext *ctx,
     return 0;
 }
 
-#define cbs_h2645_replace_ps(h26n, ps_name, ps_var, id_element) \
+
+#define cbs_h2645_replace_ps(h26n, ps_name, ps_var, id_element, buffer) \
+static AVBufferRef* cbs_h26 ## h26n ## _copy_ ## ps_var(const H26 ## h26n ## Raw ## ps_name *source)\
+{ \
+    H26 ## h26n ## Raw ## ps_name *copy; \
+    AVBufferRef *copy_ref; \
+    copy = av_malloc(sizeof(*source)); \
+    if (!copy) \
+        return NULL; \
+    memcpy(copy, source, sizeof(*source)); \
+    copy_ref = av_buffer_create((uint8_t*)copy, sizeof(*source), \
+                                FREE(h26n, ps_var), NULL, 0); \
+    if (!copy_ref) { \
+        av_free(copy); \
+        return NULL; \
+    } \
+    cbs_h2645_copy_substructure(h26n, ps_name, ps_var, buffer) \
+    return copy_ref; \
+} \
+ \
 static int cbs_h26 ## h26n ## _replace_ ## ps_var(CodedBitstreamContext *ctx, \
                                                   CodedBitstreamUnit *unit)  \
 { \
@@ -692,21 +711,43 @@ static int cbs_h26 ## h26n ## _replace_ ## ps_var(CodedBitstreamContext *ctx, \
     if (unit->content_ref) \
         priv->ps_var ## _ref[id] = av_buffer_ref(unit->content_ref); \
     else \
-        priv->ps_var ## _ref[id] = av_buffer_alloc(sizeof(*ps_var)); \
+        priv->ps_var ## _ref[id] = cbs_h26 ## h26n ## _copy_ ## ps_var(ps_var); \
     if (!priv->ps_var ## _ref[id]) \
         return AVERROR(ENOMEM); \
     priv->ps_var[id] = (H26 ## h26n ## Raw ## ps_name *)priv->ps_var ## _ref[id]->data; \
-    if (!unit->content_ref) \
-        memcpy(priv->ps_var[id], ps_var, sizeof(*ps_var)); \
     return 0; \
 }
 
 
-cbs_h2645_replace_ps(4, SPS, sps, seq_parameter_set_id)
-cbs_h2645_replace_ps(4, PPS, pps, pic_parameter_set_id)
-cbs_h2645_replace_ps(5, VPS, vps, vps_video_parameter_set_id)
-cbs_h2645_replace_ps(5, SPS, sps, sps_seq_parameter_set_id)
-cbs_h2645_replace_ps(5, PPS, pps, pps_pic_parameter_set_id)
+#define FREE(h26n, ps_var) NULL
+#define cbs_h2645_copy_substructure(h26n, ps_name, ps_var, buffer)
+cbs_h2645_replace_ps(4, SPS, sps, seq_parameter_set_id, )
+#undef cbs_h2645_copy_substructure
+#undef FREE
+
+#define FREE(h26n, ps_var) &cbs_h26 ## h26n ## _free_ ## ps_var
+#define cbs_h2645_copy_substructure(h26n, ps_name, ps_var, buffer) \
+    if (source->buffer) { \
+        copy->buffer ## _ref = av_buffer_allocz(SIZE + AV_INPUT_BUFFER_PADDING_SIZE); \
+        if (!copy->buffer) { \
+            av_buffer_unref(&copy_ref); \
+            return NULL; \
+        } \
+        copy->buffer = copy->buffer ## _ref->data; \
+        memcpy(copy->buffer, source->buffer, SIZE); \
+    }
+
+#define SIZE (copy->pic_size_in_map_units_minus1 + 1)
+cbs_h2645_replace_ps(4, PPS, pps, pic_parameter_set_id, slice_group_id)
+#undef SIZE
+
+#define SIZE ((copy->extension_data.bit_length + 7) / 8)
+cbs_h2645_replace_ps(5, VPS, vps, vps_video_parameter_set_id, extension_data.data)
+cbs_h2645_replace_ps(5, SPS, sps, sps_seq_parameter_set_id, extension_data.data)
+cbs_h2645_replace_ps(5, PPS, pps, pps_pic_parameter_set_id, extension_data.data)
+#undef SIZE
+#undef FREE
+
 
 static int cbs_h264_read_nal_unit(CodedBitstreamContext *ctx,
                                   CodedBitstreamUnit *unit)
-- 
2.19.0



More information about the ffmpeg-devel mailing list