[FFmpeg-devel] [PATCH 2/6] cbs_h2645: Do a deep copy for parameter sets
Mark Thompson
sw at jkqxz.net
Sun Nov 18 23:05:15 EET 2018
On 09/11/18 05:31, Andreas Rheinhardt wrote:
> 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; \
> +} \
I think the copy function should be split out from replace_ps, since you're calling it from other contexts in the following patches.
> + \
> 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(©_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
Could we perhaps make a single "internal buffers" argument here rather than the additional magic defines (SIZE, FREE, copy_substructure)?
Something like:
#define cbs_h2645_copy_ps_with_buffers(h26n, ps_name, ps_var, id_element, internal_buffers) \
...
struct {
uint8_t *data;
AVBufferRef *ref;
size_t size;
} bufs[] = { internal_buffers };
...
for (i = 0; i < FF_ARRAY_ELEMS(bufs); i++) {
if (bufs[i].data) {
....
}
}
(Though maybe it needs offsetof() against the structure rather than passing in names, not sure.)
> +
>
> static int cbs_h264_read_nal_unit(CodedBitstreamContext *ctx,
> CodedBitstreamUnit *unit)
>
Thanks,
- Mark
More information about the ffmpeg-devel
mailing list