static gboolean gst_video_decoder_handle_missing_data_default (GstVideoDecoder *
decoder, GstClockTime timestamp, GstClockTime duration);
+static void gst_video_decoder_replace_input_buffer (GstVideoDecoder * decoder,
+ GstVideoCodecFrame * frame, GstBuffer ** dest_buffer);
+
static void gst_video_decoder_copy_metas (GstVideoDecoder * decoder,
GstVideoCodecFrame * frame, GstBuffer * src_buffer,
GstBuffer * dest_buffer);
GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
}
- if (frame->input_buffer) {
- gst_video_decoder_copy_metas (decoder, frame, frame->input_buffer, buf);
- gst_buffer_unref (frame->input_buffer);
- }
- frame->input_buffer = buf;
+ gst_video_decoder_replace_input_buffer (decoder, frame, &buf);
if (decoder->input_segment.rate < 0.0) {
priv->parse_gather = g_list_prepend (priv->parse_gather, frame);
}
}
+static void
+gst_video_decoder_replace_input_buffer (GstVideoDecoder * decoder,
+ GstVideoCodecFrame * frame, GstBuffer ** dest_buffer)
+{
+ if (frame->input_buffer) {
+ *dest_buffer = gst_buffer_make_writable (*dest_buffer);
+ gst_video_decoder_copy_metas (decoder, frame, frame->input_buffer,
+ *dest_buffer);
+ gst_buffer_unref (frame->input_buffer);
+ }
+
+ frame->input_buffer = *dest_buffer;
+}
+
/**
* gst_video_decoder_finish_frame:
* @decoder: a #GstVideoDecoder
buffer = gst_buffer_new_and_alloc (0);
}
- if (priv->current_frame->input_buffer) {
- gst_video_decoder_copy_metas (decoder, priv->current_frame,
- priv->current_frame->input_buffer, buffer);
- gst_buffer_unref (priv->current_frame->input_buffer);
- }
- priv->current_frame->input_buffer = buffer;
+ gst_video_decoder_replace_input_buffer (decoder, priv->current_frame,
+ &buffer);
gst_video_decoder_get_buffer_info_at_offset (decoder,
priv->frame_offset, &pts, &dts, &duration, &flags);
GST_END_TEST;
+/*
+ * MODE_META_COPY: takes an extra ref to the input buffer to check metas
+ * are copied to a writable buffer.
+ * see: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4912
+ */
typedef enum
{
MODE_NONE = 0,
MODE_SUBFRAMES = 1,
MODE_PACKETIZED = 1 << 1,
MODE_META_ROI = 1 << 2,
+ MODE_META_COPY = 1 << 3,
} SubframeMode;
static void
gst_buffer_add_video_region_of_interest_meta (buffer, "face", 0, 0, 10,
10);
+ /* Take an extra ref to check that we ensure buffer is writable when copying metas
+ * https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4912
+ */
+ if (mode & MODE_META_COPY) {
+ gst_buffer_ref (buffer);
+ }
fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
fail_unless (gst_pad_push_event (mysrcpad,
gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
gst_structure_new_empty ("custom1"))));
+ if (mode & MODE_META_COPY) {
+ gst_buffer_unref (buffer);
+ }
}
/* Send EOS */
fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()));
GST_END_TEST;
+GST_START_TEST (videodecoder_playback_packetized_subframes_metadata_copy)
+{
+ videodecoder_playback_subframe_mode (MODE_SUBFRAMES |
+ MODE_PACKETIZED | MODE_META_ROI | MODE_META_COPY);
+}
+
+GST_END_TEST;
+
GST_START_TEST (videodecoder_playback_invalid_ts_packetized)
{
videodecoder_playback_invalid_ts_subframe_mode (MODE_PACKETIZED);
tcase_add_test (tc, videodecoder_playback_parsed_subframes);
tcase_add_test (tc, videodecoder_playback_packetized_subframes);
tcase_add_test (tc, videodecoder_playback_packetized_subframes_metadata);
+ tcase_add_test (tc, videodecoder_playback_packetized_subframes_metadata_copy);
tcase_add_test (tc, videodecoder_playback_invalid_ts_packetized);
tcase_add_test (tc, videodecoder_playback_invalid_ts_packetized_subframes);