From d3c5fc815e146824392c656d3daaf8060068d4a9 Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Mon, 14 Nov 2022 15:53:00 -0500 Subject: [PATCH] v4l2codecs: Allow output caps to be updated This change allow output caps to be updated even though we stay in streaming state. This is needed so that any upstream updated to fields like framerate, hdr data, etc. can result in a downstream caps event being pushed. Previously, any of these changes was being ignored and the downstream caps would not reflect it. Part-of: --- .../sys/v4l2codecs/gstv4l2codech264dec.c | 44 +++++++++++++++----- .../sys/v4l2codecs/gstv4l2codech265dec.c | 47 ++++++++++++++++------ .../sys/v4l2codecs/gstv4l2codecmpeg2dec.c | 41 +++++++++++++------ .../sys/v4l2codecs/gstv4l2codecvp8dec.c | 42 ++++++++++++++----- .../sys/v4l2codecs/gstv4l2codecvp9dec.c | 35 ++++++++++++---- 5 files changed, 154 insertions(+), 55 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codech264dec.c b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codech264dec.c index f2657c0..4ae62e9 100644 --- a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codech264dec.c +++ b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codech264dec.c @@ -75,7 +75,7 @@ struct _GstV4l2CodecH264Dec GstV4l2CodecPool *src_pool; gint min_pool_size; gboolean has_videometa; - gboolean need_negotiation; + gboolean streaming; gboolean interlaced; gboolean need_sequence; gboolean copy_frames; @@ -234,6 +234,16 @@ gst_v4l2_codec_h264_dec_close (GstVideoDecoder * decoder) } static void +gst_v4l2_codec_h264_dec_streamoff (GstV4l2CodecH264Dec * self) +{ + if (self->streaming) { + gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SINK); + gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SRC); + self->streaming = FALSE; + } +} + +static void gst_v4l2_codec_h264_dec_reset_allocation (GstV4l2CodecH264Dec * self) { if (self->sink_allocator) { @@ -253,9 +263,7 @@ gst_v4l2_codec_h264_dec_stop (GstVideoDecoder * decoder) { GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder); - gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SINK); - gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SRC); - + gst_v4l2_codec_h264_dec_streamoff (self); gst_v4l2_codec_h264_dec_reset_allocation (self); if (self->output_state) @@ -314,15 +322,11 @@ gst_v4l2_codec_h264_dec_negotiate (GstVideoDecoder * decoder) GstCaps *filter, *caps; /* Ignore downstream renegotiation request. */ - if (!self->need_negotiation) - return TRUE; - self->need_negotiation = FALSE; + if (self->streaming) + goto done; GST_DEBUG_OBJECT (self, "Negotiate"); - gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SINK); - gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SRC); - gst_v4l2_codec_h264_dec_reset_allocation (self); if (!gst_v4l2_decoder_set_sink_fmt (self->decoder, V4L2_PIX_FMT_H264_SLICE, @@ -366,6 +370,7 @@ gst_v4l2_codec_h264_dec_negotiate (GstVideoDecoder * decoder) if (self->output_state) gst_video_codec_state_unref (self->output_state); +done: self->output_state = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self), self->vinfo.finfo->format, self->display_width, @@ -377,6 +382,9 @@ gst_v4l2_codec_h264_dec_negotiate (GstVideoDecoder * decoder) self->output_state->caps = gst_video_info_to_caps (&self->output_state->info); if (GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder)) { + if (self->streaming) + return TRUE; + if (!gst_v4l2_decoder_streamon (self->decoder, GST_PAD_SINK)) { GST_ELEMENT_ERROR (self, RESOURCE, FAILED, ("Could not enable the decoder driver."), @@ -391,6 +399,8 @@ gst_v4l2_codec_h264_dec_negotiate (GstVideoDecoder * decoder) return FALSE; } + self->streaming = TRUE; + return TRUE; } @@ -404,6 +414,11 @@ gst_v4l2_codec_h264_dec_decide_allocation (GstVideoDecoder * decoder, GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder); guint min = 0, num_bitstream; + /* If we are streaming here, then it means there is nothing allocation + * related in the new state and allocation can be ignored */ + if (self->streaming) + return TRUE; + self->has_videometa = gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); @@ -894,7 +909,7 @@ gst_v4l2_codec_h264_dec_new_sequence (GstH264Decoder * decoder, self->need_sequence = TRUE; if (negotiation_needed) { - self->need_negotiation = TRUE; + gst_v4l2_codec_h264_dec_streamoff (self); if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) { GST_ERROR_OBJECT (self, "Failed to negotiate with downstream"); return GST_FLOW_NOT_NEGOTIATED; @@ -1046,6 +1061,13 @@ gst_v4l2_codec_h264_dec_output_picture (GstH264Decoder * decoder, GstV4l2Request *request = gst_h264_picture_get_user_data (picture); gint ret; + if (picture->discont_state) { + if (!gst_video_decoder_negotiate (vdec)) { + GST_ERROR_OBJECT (vdec, "Could not re-negotiate with updated state"); + return FALSE; + } + } + GST_DEBUG_OBJECT (self, "Output picture %u", picture->system_frame_number); ret = gst_v4l2_request_set_done (request); diff --git a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codech265dec.c b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codech265dec.c index 45c3e72..242c855 100644 --- a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codech265dec.c +++ b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codech265dec.c @@ -76,7 +76,7 @@ struct _GstV4l2CodecH265Dec GstV4l2CodecPool *src_pool; gint min_pool_size; gboolean has_videometa; - gboolean need_negotiation; + gboolean streaming; gboolean copy_frames; gboolean need_sequence; @@ -268,6 +268,16 @@ gst_v4l2_codec_h265_dec_close (GstVideoDecoder * decoder) } static void +gst_v4l2_codec_h265_dec_streamoff (GstV4l2CodecH265Dec * self) +{ + if (self->streaming) { + gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SINK); + gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SRC); + self->streaming = FALSE; + } +} + +static void gst_v4l2_codec_h265_dec_reset_allocation (GstV4l2CodecH265Dec * self) { if (self->sink_allocator) { @@ -287,9 +297,7 @@ gst_v4l2_codec_h265_dec_stop (GstVideoDecoder * decoder) { GstV4l2CodecH265Dec *self = GST_V4L2_CODEC_H265_DEC (decoder); - gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SINK); - gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SRC); - + gst_v4l2_codec_h265_dec_streamoff (self); gst_v4l2_codec_h265_dec_reset_allocation (self); if (self->output_state) @@ -348,15 +356,11 @@ gst_v4l2_codec_h265_dec_negotiate (GstVideoDecoder * decoder) GstCaps *filter, *caps; /* Ignore downstream renegotiation request. */ - if (!self->need_negotiation) - return TRUE; - self->need_negotiation = FALSE; + if (self->streaming) + goto done; GST_DEBUG_OBJECT (self, "Negotiate"); - gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SINK); - gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SRC); - gst_v4l2_codec_h265_dec_reset_allocation (self); if (!gst_v4l2_decoder_set_sink_fmt (self->decoder, V4L2_PIX_FMT_HEVC_SLICE, @@ -397,6 +401,7 @@ gst_v4l2_codec_h265_dec_negotiate (GstVideoDecoder * decoder) } gst_caps_unref (caps); +done: if (self->output_state) gst_video_codec_state_unref (self->output_state); @@ -408,6 +413,9 @@ gst_v4l2_codec_h265_dec_negotiate (GstVideoDecoder * decoder) self->output_state->caps = gst_video_info_to_caps (&self->output_state->info); if (GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder)) { + if (self->streaming) + return TRUE; + if (!gst_v4l2_decoder_streamon (self->decoder, GST_PAD_SINK)) { GST_ELEMENT_ERROR (self, RESOURCE, FAILED, ("Could not enable the decoder driver."), @@ -422,6 +430,8 @@ gst_v4l2_codec_h265_dec_negotiate (GstVideoDecoder * decoder) return FALSE; } + self->streaming = TRUE; + return TRUE; } @@ -435,6 +445,9 @@ gst_v4l2_codec_h265_dec_decide_allocation (GstVideoDecoder * decoder, GstV4l2CodecH265Dec *self = GST_V4L2_CODEC_H265_DEC (decoder); guint min = 0; + if (self->streaming) + return TRUE; + self->has_videometa = gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); @@ -902,7 +915,7 @@ gst_v4l2_codec_h265_dec_new_sequence (GstH265Decoder * decoder, gst_v4l2_codec_h265_dec_fill_sequence (self, sps); if (negotiation_needed) { - self->need_negotiation = TRUE; + gst_v4l2_codec_h265_dec_streamoff (self); if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) { GST_ERROR_OBJECT (self, "Failed to negotiate with downstream"); return GST_FLOW_NOT_NEGOTIATED; @@ -1174,9 +1187,17 @@ gst_v4l2_codec_h265_dec_output_picture (GstH265Decoder * decoder, GstVideoCodecFrame * frame, GstH265Picture * picture) { GstV4l2CodecH265Dec *self = GST_V4L2_CODEC_H265_DEC (decoder); + GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder); GstV4l2Request *request = gst_h265_picture_get_user_data (picture); gint ret; + if (picture->discont_state) { + if (!gst_video_decoder_negotiate (vdec)) { + GST_ERROR_OBJECT (vdec, "Could not re-negotiate with updated state"); + return FALSE; + } + } + GST_DEBUG_OBJECT (self, "Output picture %u", picture->system_frame_number); ret = gst_v4l2_request_set_done (request); @@ -1207,10 +1228,10 @@ gst_v4l2_codec_h265_dec_output_picture (GstH265Decoder * decoder, gst_h265_picture_unref (picture); - return gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame); + return gst_video_decoder_finish_frame (vdec, frame); error: - gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame); + gst_video_decoder_drop_frame (vdec, frame); gst_h265_picture_unref (picture); return GST_FLOW_ERROR; diff --git a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecmpeg2dec.c b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecmpeg2dec.c index d7982c8..00dd161 100644 --- a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecmpeg2dec.c +++ b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecmpeg2dec.c @@ -84,7 +84,7 @@ struct _GstV4l2CodecMpeg2Dec GstV4l2CodecPool *src_pool; gint min_pool_size; gboolean has_videometa; - gboolean need_negotiation; + gboolean streaming; GstMemory *bitstream; GstMapInfo bitstream_map; @@ -150,6 +150,16 @@ gst_v4l2_codec_mpeg2_dec_close (GstVideoDecoder * decoder) } static void +gst_v4l2_codec_mpeg2_dec_streamoff (GstV4l2CodecMpeg2Dec * self) +{ + if (self->streaming) { + gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SINK); + gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SRC); + self->streaming = FALSE; + } +} + +static void gst_v4l2_codec_mpeg2_dec_reset_allocation (GstV4l2CodecMpeg2Dec * self) { if (self->sink_allocator) { @@ -169,9 +179,7 @@ gst_v4l2_codec_mpeg2_dec_stop (GstVideoDecoder * decoder) { GstV4l2CodecMpeg2Dec *self = GST_V4L2_CODEC_MPEG2_DEC (decoder); - gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SINK); - gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SRC); - + gst_v4l2_codec_mpeg2_dec_streamoff (self); gst_v4l2_codec_mpeg2_dec_reset_allocation (self); if (self->output_state) @@ -236,15 +244,11 @@ gst_v4l2_codec_mpeg2_dec_negotiate (GstVideoDecoder * decoder) GstCaps *filter, *caps; /* Ignore downstream renegotiation request. */ - if (!self->need_negotiation) - return TRUE; - self->need_negotiation = FALSE; + if (self->streaming) + goto done; GST_DEBUG_OBJECT (self, "Negotiate"); - gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SINK); - gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SRC); - gst_v4l2_codec_mpeg2_dec_reset_allocation (self); if (!gst_v4l2_decoder_set_sink_fmt (self->decoder, V4L2_PIX_FMT_MPEG2_SLICE, @@ -285,6 +289,7 @@ gst_v4l2_codec_mpeg2_dec_negotiate (GstVideoDecoder * decoder) } gst_caps_unref (caps); +done: if (self->output_state) gst_video_codec_state_unref (self->output_state); @@ -300,6 +305,9 @@ gst_v4l2_codec_mpeg2_dec_negotiate (GstVideoDecoder * decoder) self->output_state->caps = gst_video_info_to_caps (&self->output_state->info); if (GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder)) { + if (self->streaming) + return TRUE; + if (!gst_v4l2_decoder_streamon (self->decoder, GST_PAD_SINK)) { GST_ELEMENT_ERROR (self, RESOURCE, FAILED, ("Could not enable the decoder driver."), @@ -314,6 +322,8 @@ gst_v4l2_codec_mpeg2_dec_negotiate (GstVideoDecoder * decoder) return FALSE; } + self->streaming = TRUE; + return TRUE; } @@ -418,7 +428,7 @@ gst_v4l2_codec_mpeg2_dec_new_sequence (GstMpeg2Decoder * decoder, GST_INFO_OBJECT (self, "Profile change %d -> %d", self->profile, mpeg_profile); self->profile = mpeg_profile; - self->need_negotiation = TRUE; + self->streaming = TRUE; } if (self->vinfo.finfo->format == GST_VIDEO_FORMAT_UNKNOWN) @@ -449,7 +459,7 @@ gst_v4l2_codec_mpeg2_dec_new_sequence (GstMpeg2Decoder * decoder, /* *INDENT-ON* */ if (negotiation_needed) { - self->need_negotiation = TRUE; + gst_v4l2_codec_mpeg2_dec_streamoff (self); if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) { GST_ERROR_OBJECT (self, "Failed to negotiate with downstream"); return GST_FLOW_ERROR; @@ -672,6 +682,13 @@ gst_v4l2_codec_mpeg2_dec_output_picture (GstMpeg2Decoder * decoder, GstV4l2Request *request = gst_mpeg2_picture_get_user_data (picture); gint ret; + if (picture->discont_state) { + if (!gst_video_decoder_negotiate (vdec)) { + GST_ERROR_OBJECT (vdec, "Could not re-negotiate with updated state"); + return FALSE; + } + } + GST_DEBUG_OBJECT (self, "Output picture %u", picture->system_frame_number); ret = gst_v4l2_request_set_done (request); diff --git a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecvp8dec.c b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecvp8dec.c index 95a6df1..2169c96 100644 --- a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecvp8dec.c +++ b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecvp8dec.c @@ -73,7 +73,7 @@ struct _GstV4l2CodecVp8Dec GstV4l2CodecPool *src_pool; gint min_pool_size; gboolean has_videometa; - gboolean need_negotiation; + gboolean streaming; gboolean copy_frames; struct v4l2_ctrl_vp8_frame frame_header; @@ -137,6 +137,16 @@ gst_v4l2_codec_vp8_dec_close (GstVideoDecoder * decoder) } static void +gst_v4l2_codec_vp8_dec_streamoff (GstV4l2CodecVp8Dec * self) +{ + if (self->streaming) { + gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SINK); + gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SRC); + self->streaming = FALSE; + } +} + +static void gst_v4l2_codec_vp8_dec_reset_allocation (GstV4l2CodecVp8Dec * self) { if (self->sink_allocator) { @@ -156,9 +166,7 @@ gst_v4l2_codec_vp8_dec_stop (GstVideoDecoder * decoder) { GstV4l2CodecVp8Dec *self = GST_V4L2_CODEC_VP8_DEC (decoder); - gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SINK); - gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SRC); - + gst_v4l2_codec_vp8_dec_streamoff (self); gst_v4l2_codec_vp8_dec_reset_allocation (self); if (self->output_state) @@ -185,15 +193,11 @@ gst_v4l2_codec_vp8_dec_negotiate (GstVideoDecoder * decoder) GstCaps *filter, *caps; /* Ignore downstream renegotiation request. */ - if (!self->need_negotiation) - return TRUE; - self->need_negotiation = FALSE; + if (self->streaming) + goto done; GST_DEBUG_OBJECT (self, "Negotiate"); - gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SINK); - gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SRC); - gst_v4l2_codec_vp8_dec_reset_allocation (self); if (!gst_v4l2_decoder_set_sink_fmt (self->decoder, V4L2_PIX_FMT_VP8_FRAME, @@ -234,6 +238,7 @@ gst_v4l2_codec_vp8_dec_negotiate (GstVideoDecoder * decoder) } gst_caps_unref (caps); +done: if (self->output_state) gst_video_codec_state_unref (self->output_state); @@ -245,6 +250,9 @@ gst_v4l2_codec_vp8_dec_negotiate (GstVideoDecoder * decoder) self->output_state->caps = gst_video_info_to_caps (&self->output_state->info); if (GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder)) { + if (self->streaming) + return TRUE; + if (!gst_v4l2_decoder_streamon (self->decoder, GST_PAD_SINK)) { GST_ELEMENT_ERROR (self, RESOURCE, FAILED, ("Could not enable the decoder driver."), @@ -259,6 +267,8 @@ gst_v4l2_codec_vp8_dec_negotiate (GstVideoDecoder * decoder) return FALSE; } + self->streaming = TRUE; + return TRUE; } @@ -273,6 +283,9 @@ gst_v4l2_codec_vp8_dec_decide_allocation (GstVideoDecoder * decoder, guint min = 0; guint num_bitstream; + if (self->streaming) + return TRUE; + self->has_videometa = gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); @@ -470,7 +483,7 @@ gst_v4l2_codec_vp8_dec_new_sequence (GstVp8Decoder * decoder, gst_v4l2_codec_vp8_dec_fill_frame_header (self, frame_hdr); if (negotiation_needed) { - self->need_negotiation = TRUE; + gst_v4l2_codec_vp8_dec_streamoff (self); if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) { GST_ERROR_OBJECT (self, "Failed to negotiate with downstream"); return GST_FLOW_NOT_NEGOTIATED; @@ -710,6 +723,13 @@ gst_v4l2_codec_vp8_dec_output_picture (GstVp8Decoder * decoder, GstV4l2Request *request = gst_vp8_picture_get_user_data (picture); gint ret; + if (picture->discont_state) { + if (!gst_video_decoder_negotiate (vdec)) { + GST_ERROR_OBJECT (vdec, "Could not re-negotiate with updated state"); + return FALSE; + } + } + GST_DEBUG_OBJECT (self, "Output picture %u", picture->system_frame_number); ret = gst_v4l2_request_set_done (request); diff --git a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecvp9dec.c b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecvp9dec.c index 5902c1b..1640155 100644 --- a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecvp9dec.c +++ b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecvp9dec.c @@ -73,7 +73,7 @@ struct _GstV4l2CodecVp9Dec GstV4l2CodecAllocator *src_allocator; GstV4l2CodecPool *src_pool; gboolean has_videometa; - gboolean need_negotiation; + gboolean streaming; gboolean copy_frames; struct v4l2_ctrl_vp9_frame v4l2_vp9_frame; @@ -402,6 +402,16 @@ gst_v4l2_codec_vp9_dec_close (GstVideoDecoder * decoder) } static void +gst_v4l2_codec_vp9_dec_streamoff (GstV4l2CodecVp9Dec * self) +{ + if (self->streaming) { + gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SINK); + gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SRC); + self->streaming = FALSE; + } +} + +static void gst_v4l2_codec_vp9_dec_reset_allocation (GstV4l2CodecVp9Dec * self) { if (self->sink_allocator) { @@ -451,15 +461,11 @@ gst_v4l2_codec_vp9_dec_negotiate (GstVideoDecoder * decoder) GstCaps *filter, *caps; /* Ignore downstream renegotiation request. */ - if (!self->need_negotiation) - return TRUE; - self->need_negotiation = FALSE; + if (self->streaming) + goto done; GST_DEBUG_OBJECT (self, "Negotiate"); - gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SINK); - gst_v4l2_decoder_streamoff (self->decoder, GST_PAD_SRC); - gst_v4l2_codec_vp9_dec_reset_allocation (self); if (!gst_v4l2_decoder_set_sink_fmt (self->decoder, V4L2_PIX_FMT_VP9_FRAME, @@ -499,6 +505,7 @@ gst_v4l2_codec_vp9_dec_negotiate (GstVideoDecoder * decoder) } gst_caps_unref (caps); +done: if (self->output_state) gst_video_codec_state_unref (self->output_state); @@ -510,6 +517,9 @@ gst_v4l2_codec_vp9_dec_negotiate (GstVideoDecoder * decoder) self->output_state->caps = gst_video_info_to_caps (&self->output_state->info); if (GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder)) { + if (self->streaming) + return TRUE; + if (!gst_v4l2_decoder_streamon (self->decoder, GST_PAD_SINK)) { GST_ELEMENT_ERROR (self, RESOURCE, FAILED, ("Could not enable the decoder driver."), @@ -524,6 +534,8 @@ gst_v4l2_codec_vp9_dec_negotiate (GstVideoDecoder * decoder) return FALSE; } + self->streaming = TRUE; + return TRUE; } @@ -645,7 +657,7 @@ gst_v4l2_codec_vp9_dec_new_sequence (GstVp9Decoder * decoder, gst_v4l2_codec_vp9_dec_fill_prob_updates (self, frame_hdr); if (negotiation_needed) { - self->need_negotiation = TRUE; + gst_v4l2_codec_vp9_dec_streamoff (self); if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) { GST_ERROR_OBJECT (self, "Failed to negotiate with downstream"); return GST_FLOW_ERROR; @@ -932,6 +944,13 @@ gst_v4l2_codec_vp9_dec_output_picture (GstVp9Decoder * decoder, GstV4l2Request *request = NULL; gint ret; + if (picture->discont_state) { + if (!gst_video_decoder_negotiate (vdec)) { + GST_ERROR_OBJECT (vdec, "Could not re-negotiate with updated state"); + return FALSE; + } + } + GST_DEBUG_OBJECT (self, "Output picture %u", picture->system_frame_number); if (!GST_MINI_OBJECT_FLAG_IS_SET (picture, FLAG_PICTURE_HOLDS_BUFFER)) -- 2.7.4