mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-29 13:11:06 +00:00
v4l2codecs: vp9: Allow inter-frames resolution change
When the stream resolution change it is needed to negotiate a new pools and to update the caps. Resolution change could occurs on a new sequence or a new picture so move resolution change detection code in a common function. For memory allocation reasons, only allows resolution change on non keyframe if the driver support remove buffer feature. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7684>
This commit is contained in:
parent
34997e88ae
commit
e13065b22a
1 changed files with 61 additions and 26 deletions
|
@ -86,6 +86,7 @@ struct _GstV4l2CodecVp9Dec
|
||||||
gboolean has_videometa;
|
gboolean has_videometa;
|
||||||
gboolean streaming;
|
gboolean streaming;
|
||||||
gboolean copy_frames;
|
gboolean copy_frames;
|
||||||
|
gboolean need_negotiation;
|
||||||
|
|
||||||
struct v4l2_ctrl_vp9_frame v4l2_vp9_frame;
|
struct v4l2_ctrl_vp9_frame v4l2_vp9_frame;
|
||||||
struct v4l2_ctrl_vp9_compressed_hdr v4l2_delta_probs;
|
struct v4l2_ctrl_vp9_compressed_hdr v4l2_delta_probs;
|
||||||
|
@ -400,9 +401,8 @@ gst_v4l2_codec_vp9_dec_open (GstVideoDecoder * decoder)
|
||||||
gst_v4l2_decoder_query_control_size (self->decoder,
|
gst_v4l2_decoder_query_control_size (self->decoder,
|
||||||
V4L2_CID_STATELESS_VP9_COMPRESSED_HDR, NULL);
|
V4L2_CID_STATELESS_VP9_COMPRESSED_HDR, NULL);
|
||||||
|
|
||||||
/* V4L2 does not support non-keyframe resolution change, this will ask the
|
gst_vp9_decoder_set_non_keyframe_format_change_support (vp9dec,
|
||||||
* base class to drop frame until the next keyframe as a workaround. */
|
gst_v4l2_decoder_has_remove_bufs (self->decoder));
|
||||||
gst_vp9_decoder_set_non_keyframe_format_change_support (vp9dec, FALSE);
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -477,9 +477,11 @@ gst_v4l2_codec_vp9_dec_negotiate (GstVideoDecoder * decoder)
|
||||||
GstStaticCaps *static_filter;
|
GstStaticCaps *static_filter;
|
||||||
|
|
||||||
/* Ignore downstream renegotiation request. */
|
/* Ignore downstream renegotiation request. */
|
||||||
if (self->streaming)
|
if (!self->need_negotiation)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
self->need_negotiation = FALSE;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (self, "Negotiate");
|
GST_DEBUG_OBJECT (self, "Negotiate");
|
||||||
|
|
||||||
gst_v4l2_codec_vp9_dec_reset_allocation (self);
|
gst_v4l2_codec_vp9_dec_reset_allocation (self);
|
||||||
|
@ -571,11 +573,6 @@ gst_v4l2_codec_vp9_dec_decide_allocation (GstVideoDecoder * decoder,
|
||||||
guint min = 0;
|
guint min = 0;
|
||||||
guint num_bitstream;
|
guint 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)
|
|
||||||
goto no_internal_changes;
|
|
||||||
|
|
||||||
g_clear_object (&self->src_pool);
|
g_clear_object (&self->src_pool);
|
||||||
g_clear_object (&self->src_allocator);
|
g_clear_object (&self->src_allocator);
|
||||||
|
|
||||||
|
@ -621,7 +618,6 @@ gst_v4l2_codec_vp9_dec_decide_allocation (GstVideoDecoder * decoder,
|
||||||
|
|
||||||
self->src_pool = gst_v4l2_codec_pool_new (self->src_allocator, &self->vinfo);
|
self->src_pool = gst_v4l2_codec_pool_new (self->src_allocator, &self->vinfo);
|
||||||
|
|
||||||
no_internal_changes:
|
|
||||||
/* Our buffer pool is internal, we will let the base class create a video
|
/* Our buffer pool is internal, we will let the base class create a video
|
||||||
* pool, and use it if we are running out of buffers or if downstream does
|
* pool, and use it if we are running out of buffers or if downstream does
|
||||||
* not support GstVideoMeta */
|
* not support GstVideoMeta */
|
||||||
|
@ -629,23 +625,21 @@ no_internal_changes:
|
||||||
(decoder, query);
|
(decoder, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static gboolean
|
||||||
gst_v4l2_codec_vp9_dec_new_sequence (GstVp9Decoder * decoder,
|
gst_v4l2_codec_vp9_dec_is_format_change (GstV4l2CodecVp9Dec * self,
|
||||||
const GstVp9FrameHeader * frame_hdr, gint max_dpb_size)
|
const GstVp9FrameHeader * frame_hdr)
|
||||||
{
|
{
|
||||||
GstV4l2CodecVp9Dec *self = GST_V4L2_CODEC_VP9_DEC (decoder);
|
gboolean ret = FALSE;
|
||||||
gboolean negotiation_needed = FALSE;
|
|
||||||
|
|
||||||
if (self->vinfo.finfo->format == GST_VIDEO_FORMAT_UNKNOWN)
|
if (self->vinfo.finfo->format == GST_VIDEO_FORMAT_UNKNOWN)
|
||||||
negotiation_needed = TRUE;
|
ret = TRUE;
|
||||||
|
|
||||||
/* TODO Check if current buffers are large enough, and reuse them */
|
|
||||||
if (self->width != frame_hdr->width || self->height != frame_hdr->height) {
|
if (self->width != frame_hdr->width || self->height != frame_hdr->height) {
|
||||||
self->width = frame_hdr->width;
|
self->width = frame_hdr->width;
|
||||||
self->height = frame_hdr->height;
|
self->height = frame_hdr->height;
|
||||||
negotiation_needed = TRUE;
|
GST_DEBUG_OBJECT (self, "Resolution changed to %dx%d",
|
||||||
GST_INFO_OBJECT (self, "Resolution changed to %dx%d",
|
|
||||||
self->width, self->height);
|
self->width, self->height);
|
||||||
|
ret = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->subsampling_x != frame_hdr->subsampling_x ||
|
if (self->subsampling_x != frame_hdr->subsampling_x ||
|
||||||
|
@ -656,7 +650,7 @@ gst_v4l2_codec_vp9_dec_new_sequence (GstVp9Decoder * decoder,
|
||||||
frame_hdr->subsampling_x, frame_hdr->subsampling_y);
|
frame_hdr->subsampling_x, frame_hdr->subsampling_y);
|
||||||
self->subsampling_x = frame_hdr->subsampling_x;
|
self->subsampling_x = frame_hdr->subsampling_x;
|
||||||
self->subsampling_y = frame_hdr->subsampling_y;
|
self->subsampling_y = frame_hdr->subsampling_y;
|
||||||
negotiation_needed = TRUE;
|
ret = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frame_hdr->color_space != GST_VP9_CS_UNKNOWN &&
|
if (frame_hdr->color_space != GST_VP9_CS_UNKNOWN &&
|
||||||
|
@ -665,14 +659,14 @@ gst_v4l2_codec_vp9_dec_new_sequence (GstVp9Decoder * decoder,
|
||||||
GST_DEBUG_OBJECT (self, "colorspace changed from %d to %d",
|
GST_DEBUG_OBJECT (self, "colorspace changed from %d to %d",
|
||||||
self->color_space, frame_hdr->color_space);
|
self->color_space, frame_hdr->color_space);
|
||||||
self->color_space = frame_hdr->color_space;
|
self->color_space = frame_hdr->color_space;
|
||||||
negotiation_needed = TRUE;
|
ret = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frame_hdr->color_range != self->color_range) {
|
if (frame_hdr->color_range != self->color_range) {
|
||||||
GST_DEBUG_OBJECT (self, "color range changed from %d to %d",
|
GST_DEBUG_OBJECT (self, "color range changed from %d to %d",
|
||||||
self->color_range, frame_hdr->color_range);
|
self->color_range, frame_hdr->color_range);
|
||||||
self->color_range = frame_hdr->color_range;
|
self->color_range = frame_hdr->color_range;
|
||||||
negotiation_needed = TRUE;
|
ret = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frame_hdr->profile != GST_VP9_PROFILE_UNDEFINED &&
|
if (frame_hdr->profile != GST_VP9_PROFILE_UNDEFINED &&
|
||||||
|
@ -680,23 +674,61 @@ gst_v4l2_codec_vp9_dec_new_sequence (GstVp9Decoder * decoder,
|
||||||
GST_DEBUG_OBJECT (self, "profile changed from %d to %d", self->profile,
|
GST_DEBUG_OBJECT (self, "profile changed from %d to %d", self->profile,
|
||||||
frame_hdr->profile);
|
frame_hdr->profile);
|
||||||
self->profile = frame_hdr->profile;
|
self->profile = frame_hdr->profile;
|
||||||
negotiation_needed = TRUE;
|
ret = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frame_hdr->bit_depth != self->bit_depth) {
|
if (frame_hdr->bit_depth != self->bit_depth) {
|
||||||
GST_DEBUG_OBJECT (self, "bit-depth changed from %d to %d",
|
GST_DEBUG_OBJECT (self, "bit-depth changed from %d to %d",
|
||||||
self->bit_depth, frame_hdr->bit_depth);
|
self->bit_depth, frame_hdr->bit_depth);
|
||||||
self->bit_depth = frame_hdr->bit_depth;
|
self->bit_depth = frame_hdr->bit_depth;
|
||||||
negotiation_needed = TRUE;
|
ret = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_v4l2_codec_vp9_dec_new_picture (GstVp9Decoder * decoder,
|
||||||
|
GstVideoCodecFrame * frame, GstVp9Picture * picture)
|
||||||
|
{
|
||||||
|
GstV4l2CodecVp9Dec *self = GST_V4L2_CODEC_VP9_DEC (decoder);
|
||||||
|
|
||||||
|
self->need_negotiation =
|
||||||
|
gst_v4l2_codec_vp9_dec_is_format_change (self, &picture->frame_hdr);
|
||||||
|
|
||||||
|
if (!self->need_negotiation)
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
|
||||||
|
if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
|
||||||
|
GST_ERROR_OBJECT (self, "Failed to negotiate with downstream");
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_v4l2_codec_vp9_dec_new_sequence (GstVp9Decoder * decoder,
|
||||||
|
const GstVp9FrameHeader * frame_hdr, gint max_dpb_size)
|
||||||
|
{
|
||||||
|
GstV4l2CodecVp9Dec *self = GST_V4L2_CODEC_VP9_DEC (decoder);
|
||||||
|
|
||||||
|
/* TODO Check if current buffers are large enough, and reuse them */
|
||||||
|
self->need_negotiation =
|
||||||
|
gst_v4l2_codec_vp9_dec_is_format_change (self, frame_hdr);
|
||||||
|
|
||||||
gst_v4l2_codec_vp9_dec_fill_dec_params (self, frame_hdr, NULL);
|
gst_v4l2_codec_vp9_dec_fill_dec_params (self, frame_hdr, NULL);
|
||||||
|
|
||||||
if (decoder->parse_compressed_headers)
|
if (decoder->parse_compressed_headers)
|
||||||
gst_v4l2_codec_vp9_dec_fill_prob_updates (self, frame_hdr);
|
gst_v4l2_codec_vp9_dec_fill_prob_updates (self, frame_hdr);
|
||||||
|
|
||||||
if (negotiation_needed) {
|
if (self->need_negotiation) {
|
||||||
|
/* If the negotiation request occurs on a key frame or
|
||||||
|
* remove buffer isn't supported do a stream off */
|
||||||
|
if ((frame_hdr->frame_type == GST_VP9_KEY_FRAME)
|
||||||
|
|| !gst_v4l2_decoder_has_remove_bufs (self->decoder)) {
|
||||||
gst_v4l2_codec_vp9_dec_streamoff (self);
|
gst_v4l2_codec_vp9_dec_streamoff (self);
|
||||||
|
}
|
||||||
if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
|
if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
|
||||||
GST_ERROR_OBJECT (self, "Failed to negotiate with downstream");
|
GST_ERROR_OBJECT (self, "Failed to negotiate with downstream");
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
|
@ -1131,6 +1163,7 @@ gst_v4l2_codec_vp9_dec_get_property (GObject * object, guint prop_id,
|
||||||
static void
|
static void
|
||||||
gst_v4l2_codec_vp9_dec_init (GstV4l2CodecVp9Dec * self)
|
gst_v4l2_codec_vp9_dec_init (GstV4l2CodecVp9Dec * self)
|
||||||
{
|
{
|
||||||
|
self->need_negotiation = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1194,6 +1227,8 @@ gst_v4l2_codec_vp9_dec_subclass_init (GstV4l2CodecVp9DecClass * klass,
|
||||||
|
|
||||||
vp9decoder_class->new_sequence =
|
vp9decoder_class->new_sequence =
|
||||||
GST_DEBUG_FUNCPTR (gst_v4l2_codec_vp9_dec_new_sequence);
|
GST_DEBUG_FUNCPTR (gst_v4l2_codec_vp9_dec_new_sequence);
|
||||||
|
vp9decoder_class->new_picture =
|
||||||
|
GST_DEBUG_FUNCPTR (gst_v4l2_codec_vp9_dec_new_picture);
|
||||||
vp9decoder_class->start_picture =
|
vp9decoder_class->start_picture =
|
||||||
GST_DEBUG_FUNCPTR (gst_v4l2_codec_vp9_dec_start_picture);
|
GST_DEBUG_FUNCPTR (gst_v4l2_codec_vp9_dec_start_picture);
|
||||||
vp9decoder_class->decode_picture =
|
vp9decoder_class->decode_picture =
|
||||||
|
|
Loading…
Reference in a new issue