v4l2codecs/av1decoder: Allow output caps to be updated

To bring AV1 in line - needed for the next commit.

See: d3c5fc815e ("v4l2codecs: Allow output caps to be updated")
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5896>
This commit is contained in:
Robert Mader 2024-01-08 23:45:58 +01:00 committed by Nicolas Dufresne
parent 97ebaa0bc1
commit 75b7e5fcb3

View file

@ -69,7 +69,7 @@ struct _GstV4l2CodecAV1Dec
GstV4l2CodecPool *src_pool;
gint min_pool_size;
gboolean has_videometa;
gboolean need_negotiation;
gboolean streaming;
gboolean copy_frames;
gint frame_width;
@ -220,6 +220,16 @@ gst_v4l2_codec_av1_dec_close (GstVideoDecoder * decoder)
return TRUE;
}
static void
gst_v4l2_codec_av1_dec_streamoff (GstV4l2CodecAV1Dec * 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_av1_dec_reset_allocation (GstV4l2CodecAV1Dec * self)
{
@ -270,15 +280,11 @@ gst_v4l2_codec_av1_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_av1_dec_reset_allocation (self);
if (!gst_v4l2_decoder_set_sink_fmt (self->decoder, V4L2_PIX_FMT_AV1_FRAME,
@ -318,6 +324,7 @@ gst_v4l2_codec_av1_dec_negotiate (GstVideoDecoder * decoder)
}
gst_caps_unref (caps);
done:
if (self->output_state)
gst_video_codec_state_unref (self->output_state);
@ -329,6 +336,9 @@ gst_v4l2_codec_av1_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."),
@ -343,6 +353,8 @@ gst_v4l2_codec_av1_dec_negotiate (GstVideoDecoder * decoder)
return FALSE;
}
self->streaming = TRUE;
return TRUE;
}
@ -1010,6 +1022,7 @@ gst_v4l2_codec_av1_dec_new_picture (GstAV1Decoder * decoder,
GstV4l2CodecAV1Dec *self = GST_V4L2_CODEC_AV1_DEC (decoder);
GstAV1FrameHeaderOBU *frame_hdr = &picture->frame_hdr;
struct v4l2_ctrl_av1_sequence *seq_hdr = &self->v4l2_sequence;
gboolean negotiation_needed = FALSE;
gint max_width;
gint max_height;
@ -1017,7 +1030,7 @@ gst_v4l2_codec_av1_dec_new_picture (GstAV1Decoder * decoder,
max_height = seq_hdr->max_frame_height_minus_1 + 1;
if (self->vinfo.finfo->format == GST_VIDEO_FORMAT_UNKNOWN)
self->need_negotiation = TRUE;
negotiation_needed = TRUE;
/* FIXME the base class could signal this, but let's assume that when we
* have spatial layers, that smaller resolution will never be shown, and
@ -1027,7 +1040,7 @@ gst_v4l2_codec_av1_dec_new_picture (GstAV1Decoder * decoder,
self->frame_width = self->render_width = max_width;
self->frame_height = self->render_height = max_height;
self->need_negotiation = TRUE;
negotiation_needed = TRUE;
GST_INFO_OBJECT (self, "max {width|height} changed to %dx%d",
self->frame_width, self->frame_height);
@ -1052,7 +1065,7 @@ gst_v4l2_codec_av1_dec_new_picture (GstAV1Decoder * decoder,
self->render_width = frame_hdr->render_width;
self->render_height = frame_hdr->render_height;
self->need_negotiation = TRUE;
negotiation_needed = TRUE;
GST_INFO_OBJECT (self, "frame {width|height} changed to %dx%d",
self->frame_width, self->frame_height);
@ -1064,7 +1077,7 @@ gst_v4l2_codec_av1_dec_new_picture (GstAV1Decoder * decoder,
GST_DEBUG_OBJECT (self, "bit-depth changed from %d to %d", self->bit_depth,
seq_hdr->bit_depth);
self->bit_depth = seq_hdr->bit_depth;
self->need_negotiation = TRUE;
negotiation_needed = TRUE;
}
if (self->profile != GST_AV1_PROFILE_UNDEFINED &&
@ -1072,23 +1085,24 @@ gst_v4l2_codec_av1_dec_new_picture (GstAV1Decoder * decoder,
GST_DEBUG_OBJECT (self, "profile changed from %d to %d", self->profile,
seq_hdr->seq_profile);
self->profile = seq_hdr->seq_profile;
self->need_negotiation = TRUE;
negotiation_needed = TRUE;
}
if (seq_hdr->bit_depth != self->bit_depth) {
GST_DEBUG_OBJECT (self, "bit-depth changed from %d to %d",
self->bit_depth, seq_hdr->bit_depth);
self->bit_depth = seq_hdr->bit_depth;
self->need_negotiation = TRUE;
negotiation_needed = TRUE;
}
if (self->need_negotiation) {
if (negotiation_needed) {
if (frame_hdr->frame_type != GST_AV1_KEY_FRAME) {
GST_ERROR_OBJECT (self,
"Inter-frame resolution changes are not yet supported in v4l2");
return GST_FLOW_ERROR;
}
gst_v4l2_codec_av1_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;
@ -1393,6 +1407,13 @@ gst_v4l2_codec_av1_dec_output_picture (GstAV1Decoder * decoder,
GstCodecPicture *codec_picture = GST_CODEC_PICTURE (picture);
gint ret;
if (codec_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",
codec_picture->system_frame_number);