mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-22 16:26:39 +00:00
v4l2: videodec: Move pool setup inside negotiate()
Move all the pool configuration inside the negotiate() virtual function. This allow settting up a pool with default format whenever the base class wants to start without input data, like gaps. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4590>
This commit is contained in:
parent
8230c927f0
commit
c293ebc039
1 changed files with 174 additions and 191 deletions
|
@ -358,23 +358,174 @@ gst_v4l2_video_dec_flush (GstVideoDecoder * decoder)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_v4l2_video_remove_padding (GstCapsFeatures * features,
|
||||
GstStructure * structure, gpointer user_data)
|
||||
{
|
||||
GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (user_data);
|
||||
GstVideoAlignment *align = &self->v4l2capture->align;
|
||||
GstVideoInfo *info = &self->v4l2capture->info;
|
||||
int width, height;
|
||||
|
||||
if (!gst_structure_get_int (structure, "width", &width))
|
||||
return TRUE;
|
||||
|
||||
if (!gst_structure_get_int (structure, "height", &height))
|
||||
return TRUE;
|
||||
|
||||
if (align->padding_left != 0 || align->padding_top != 0 ||
|
||||
height != info->height + align->padding_bottom)
|
||||
return TRUE;
|
||||
|
||||
if (height == info->height + align->padding_bottom) {
|
||||
/* Some drivers may round up width to the padded with */
|
||||
if (width == info->width + align->padding_right)
|
||||
gst_structure_set (structure,
|
||||
"width", G_TYPE_INT, width - align->padding_right,
|
||||
"height", G_TYPE_INT, height - align->padding_bottom, NULL);
|
||||
/* Some drivers may keep visible width and only round up bytesperline */
|
||||
else if (width == info->width)
|
||||
gst_structure_set (structure,
|
||||
"height", G_TYPE_INT, height - align->padding_bottom, NULL);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_v4l2_video_dec_negotiate (GstVideoDecoder * decoder)
|
||||
{
|
||||
GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
|
||||
GstV4l2Error error = GST_V4L2_ERROR_INIT;
|
||||
GstVideoInfo info;
|
||||
GstVideoCodecState *output_state;
|
||||
GstCaps *acquired_caps, *fixation_caps, *available_caps, *caps, *filter;
|
||||
GstStructure *st;
|
||||
gboolean active;
|
||||
GstBufferPool *cpool;
|
||||
gboolean ret;
|
||||
|
||||
/* We don't allow renegotiation without careful disabling the pool */
|
||||
{
|
||||
GstBufferPool *cpool = gst_v4l2_object_get_buffer_pool (self->v4l2capture);
|
||||
if (cpool) {
|
||||
gboolean is_active = gst_buffer_pool_is_active (cpool);
|
||||
gst_object_unref (cpool);
|
||||
if (is_active)
|
||||
return TRUE;
|
||||
}
|
||||
cpool = gst_v4l2_object_get_buffer_pool (self->v4l2capture);
|
||||
if (cpool) {
|
||||
gboolean is_active = gst_buffer_pool_is_active (cpool);
|
||||
gst_object_unref (cpool);
|
||||
if (is_active)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
|
||||
/* init capture fps according to output */
|
||||
self->v4l2capture->info.fps_d = self->v4l2output->info.fps_d;
|
||||
self->v4l2capture->info.fps_n = self->v4l2output->info.fps_n;
|
||||
|
||||
/* For decoders G_FMT returns coded size, G_SELECTION returns visible size
|
||||
* in the compose rectangle. gst_v4l2_object_acquire_format() checks both
|
||||
* and returns the visible size as with/height and the coded size as
|
||||
* padding. */
|
||||
if (!gst_v4l2_object_acquire_format (self->v4l2capture, &info))
|
||||
goto not_negotiated;
|
||||
|
||||
/* gst_v4l2_object_acquire_format() does not set fps, copy from sink */
|
||||
info.fps_n = self->v4l2output->info.fps_n;
|
||||
info.fps_d = self->v4l2output->info.fps_d;
|
||||
|
||||
gst_caps_replace (&self->probed_srccaps, NULL);
|
||||
self->probed_srccaps = gst_v4l2_object_probe_caps (self->v4l2capture,
|
||||
gst_v4l2_object_get_raw_caps ());
|
||||
/* Create caps from the acquired format, remove the format field */
|
||||
acquired_caps = gst_video_info_to_caps (&info);
|
||||
GST_DEBUG_OBJECT (self, "Acquired caps: %" GST_PTR_FORMAT, acquired_caps);
|
||||
fixation_caps = gst_caps_copy (acquired_caps);
|
||||
st = gst_caps_get_structure (fixation_caps, 0);
|
||||
gst_structure_remove_fields (st, "format", "colorimetry", "chroma-site",
|
||||
NULL);
|
||||
|
||||
/* Probe currently available pixel formats */
|
||||
available_caps = gst_caps_copy (self->probed_srccaps);
|
||||
GST_DEBUG_OBJECT (self, "Available caps: %" GST_PTR_FORMAT, available_caps);
|
||||
|
||||
/* Replace coded size with visible size, we want to negotiate visible size
|
||||
* with downstream, not coded size. */
|
||||
gst_caps_map_in_place (available_caps, gst_v4l2_video_remove_padding, self);
|
||||
|
||||
filter = gst_caps_intersect_full (available_caps, fixation_caps,
|
||||
GST_CAPS_INTERSECT_FIRST);
|
||||
GST_DEBUG_OBJECT (self, "Filtered caps: %" GST_PTR_FORMAT, filter);
|
||||
gst_caps_unref (fixation_caps);
|
||||
gst_caps_unref (available_caps);
|
||||
caps = gst_pad_peer_query_caps (decoder->srcpad, filter);
|
||||
gst_caps_unref (filter);
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Possible decoded caps: %" GST_PTR_FORMAT, caps);
|
||||
if (gst_caps_is_empty (caps)) {
|
||||
gst_caps_unref (caps);
|
||||
goto not_negotiated;
|
||||
}
|
||||
|
||||
/* Prefer the acquired caps over anything suggested downstream, this ensure
|
||||
* that we preserves the bit depth, as we don't have any fancy fixation
|
||||
* process */
|
||||
if (gst_caps_is_subset (acquired_caps, caps)) {
|
||||
gst_caps_unref (acquired_caps);
|
||||
goto use_acquired_caps;
|
||||
}
|
||||
|
||||
/* Fixate pixel format */
|
||||
caps = gst_caps_fixate (caps);
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Chosen decoded caps: %" GST_PTR_FORMAT, caps);
|
||||
|
||||
/* Try to set negotiated format, on success replace acquired format */
|
||||
if (gst_v4l2_object_set_format (self->v4l2capture, caps, &error))
|
||||
gst_video_info_from_caps (&info, caps);
|
||||
else
|
||||
gst_v4l2_clear_error (&error);
|
||||
|
||||
use_acquired_caps:
|
||||
gst_caps_unref (caps);
|
||||
|
||||
/* catch possible bogus driver that don't enumerate the format it actually
|
||||
* returned from G_FMT */
|
||||
if (!self->v4l2capture->fmtdesc)
|
||||
goto not_negotiated;
|
||||
|
||||
output_state = gst_video_decoder_set_output_state (decoder,
|
||||
info.finfo->format, info.width, info.height, self->input_state);
|
||||
|
||||
/* Copy the rest of the information, there might be more in the future */
|
||||
output_state->info.interlace_mode = info.interlace_mode;
|
||||
output_state->info.colorimetry = info.colorimetry;
|
||||
gst_video_codec_state_unref (output_state);
|
||||
|
||||
ret = GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
|
||||
if (!ret)
|
||||
goto not_negotiated;
|
||||
|
||||
/* The pool may be created through gst_video_decoder_negotiate(), so must
|
||||
* be kept after */
|
||||
cpool = gst_v4l2_object_get_buffer_pool (self->v4l2capture);
|
||||
gst_v4l2_buffer_pool_enable_resolution_change (GST_V4L2_BUFFER_POOL (cpool));
|
||||
|
||||
/* Ensure our internal pool is activated */
|
||||
active = gst_buffer_pool_set_active (cpool, TRUE);
|
||||
if (cpool)
|
||||
gst_object_unref (cpool);
|
||||
if (!active)
|
||||
goto activate_failed;
|
||||
|
||||
return TRUE;
|
||||
|
||||
not_negotiated:
|
||||
GST_ERROR_OBJECT (self, "not negotiated");
|
||||
gst_v4l2_error (self, &error);
|
||||
gst_v4l2_object_stop (self->v4l2capture);
|
||||
return FALSE;
|
||||
activate_failed:
|
||||
GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
|
||||
(_("Failed to allocate required memory.")),
|
||||
("Buffer pool activation failed"));
|
||||
gst_v4l2_object_stop (self->v4l2capture);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -532,175 +683,6 @@ check_system_frame_number_too_old (guint32 current, guint32 old)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_v4l2_video_remove_padding (GstCapsFeatures * features,
|
||||
GstStructure * structure, gpointer user_data)
|
||||
{
|
||||
GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (user_data);
|
||||
GstVideoAlignment *align = &self->v4l2capture->align;
|
||||
GstVideoInfo *info = &self->v4l2capture->info;
|
||||
int width, height;
|
||||
|
||||
if (!gst_structure_get_int (structure, "width", &width))
|
||||
return TRUE;
|
||||
|
||||
if (!gst_structure_get_int (structure, "height", &height))
|
||||
return TRUE;
|
||||
|
||||
if (align->padding_left != 0 || align->padding_top != 0 ||
|
||||
height != info->height + align->padding_bottom)
|
||||
return TRUE;
|
||||
|
||||
if (height == info->height + align->padding_bottom) {
|
||||
/* Some drivers may round up width to the padded with */
|
||||
if (width == info->width + align->padding_right)
|
||||
gst_structure_set (structure,
|
||||
"width", G_TYPE_INT, width - align->padding_right,
|
||||
"height", G_TYPE_INT, height - align->padding_bottom, NULL);
|
||||
/* Some drivers may keep visible width and only round up bytesperline */
|
||||
else if (width == info->width)
|
||||
gst_structure_set (structure,
|
||||
"height", G_TYPE_INT, height - align->padding_bottom, NULL);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_v4l2_video_dec_setup_capture (GstVideoDecoder * decoder)
|
||||
{
|
||||
GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
|
||||
GstV4l2Error error = GST_V4L2_ERROR_INIT;
|
||||
GstVideoInfo info;
|
||||
GstVideoCodecState *output_state;
|
||||
GstCaps *acquired_caps, *fixation_caps, *available_caps, *caps, *filter;
|
||||
GstStructure *st;
|
||||
GstBufferPool *cpool;
|
||||
gboolean active;
|
||||
|
||||
if (G_UNLIKELY (!GST_V4L2_IS_ACTIVE (self->v4l2capture))) {
|
||||
/* init capture fps according to output */
|
||||
self->v4l2capture->info.fps_d = self->v4l2output->info.fps_d;
|
||||
self->v4l2capture->info.fps_n = self->v4l2output->info.fps_n;
|
||||
|
||||
/* For decoders G_FMT returns coded size, G_SELECTION returns visible size
|
||||
* in the compose rectangle. gst_v4l2_object_acquire_format() checks both
|
||||
* and returns the visible size as with/height and the coded size as
|
||||
* padding. */
|
||||
if (!gst_v4l2_object_acquire_format (self->v4l2capture, &info))
|
||||
goto not_negotiated;
|
||||
|
||||
/* gst_v4l2_object_acquire_format() does not set fps, copy from sink */
|
||||
info.fps_n = self->v4l2output->info.fps_n;
|
||||
info.fps_d = self->v4l2output->info.fps_d;
|
||||
|
||||
gst_caps_replace (&self->probed_srccaps, NULL);
|
||||
self->probed_srccaps = gst_v4l2_object_probe_caps (self->v4l2capture,
|
||||
gst_v4l2_object_get_raw_caps ());
|
||||
/* Create caps from the acquired format, remove the format field */
|
||||
acquired_caps = gst_video_info_to_caps (&info);
|
||||
GST_DEBUG_OBJECT (self, "Acquired caps: %" GST_PTR_FORMAT, acquired_caps);
|
||||
fixation_caps = gst_caps_copy (acquired_caps);
|
||||
st = gst_caps_get_structure (fixation_caps, 0);
|
||||
gst_structure_remove_fields (st, "format", "colorimetry", "chroma-site",
|
||||
NULL);
|
||||
|
||||
/* Probe currently available pixel formats */
|
||||
available_caps = gst_caps_copy (self->probed_srccaps);
|
||||
GST_DEBUG_OBJECT (self, "Available caps: %" GST_PTR_FORMAT, available_caps);
|
||||
|
||||
/* Replace coded size with visible size, we want to negotiate visible size
|
||||
* with downstream, not coded size. */
|
||||
gst_caps_map_in_place (available_caps, gst_v4l2_video_remove_padding, self);
|
||||
|
||||
filter = gst_caps_intersect_full (available_caps, fixation_caps,
|
||||
GST_CAPS_INTERSECT_FIRST);
|
||||
GST_DEBUG_OBJECT (self, "Filtered caps: %" GST_PTR_FORMAT, filter);
|
||||
gst_caps_unref (fixation_caps);
|
||||
gst_caps_unref (available_caps);
|
||||
caps = gst_pad_peer_query_caps (decoder->srcpad, filter);
|
||||
gst_caps_unref (filter);
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Possible decoded caps: %" GST_PTR_FORMAT, caps);
|
||||
if (gst_caps_is_empty (caps)) {
|
||||
gst_caps_unref (caps);
|
||||
goto not_negotiated;
|
||||
}
|
||||
|
||||
/* Prefer the acquired caps over anything suggested downstream, this ensure
|
||||
* that we preserves the bit depth, as we don't have any fancy fixation
|
||||
* process */
|
||||
if (gst_caps_is_subset (acquired_caps, caps)) {
|
||||
gst_caps_unref (acquired_caps);
|
||||
goto use_acquired_caps;
|
||||
}
|
||||
|
||||
/* Fixate pixel format */
|
||||
caps = gst_caps_fixate (caps);
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Chosen decoded caps: %" GST_PTR_FORMAT, caps);
|
||||
|
||||
/* Try to set negotiated format, on success replace acquired format */
|
||||
if (gst_v4l2_object_set_format (self->v4l2capture, caps, &error))
|
||||
gst_video_info_from_caps (&info, caps);
|
||||
else
|
||||
gst_v4l2_clear_error (&error);
|
||||
|
||||
use_acquired_caps:
|
||||
gst_caps_unref (caps);
|
||||
|
||||
/* catch possible bogus driver that don't enumerate the format it actually
|
||||
* returned from G_FMT */
|
||||
if (!self->v4l2capture->fmtdesc)
|
||||
goto not_negotiated;
|
||||
|
||||
output_state = gst_video_decoder_set_output_state (decoder,
|
||||
info.finfo->format, info.width, info.height, self->input_state);
|
||||
|
||||
/* Copy the rest of the information, there might be more in the future */
|
||||
output_state->info.interlace_mode = info.interlace_mode;
|
||||
output_state->info.colorimetry = info.colorimetry;
|
||||
gst_video_codec_state_unref (output_state);
|
||||
|
||||
if (!gst_video_decoder_negotiate (decoder)) {
|
||||
if (GST_PAD_IS_FLUSHING (decoder->srcpad))
|
||||
goto flushing;
|
||||
else
|
||||
goto not_negotiated;
|
||||
}
|
||||
|
||||
/* The pool may be created through gst_video_decoder_negotiate(), so must
|
||||
* be kept after */
|
||||
cpool = gst_v4l2_object_get_buffer_pool (self->v4l2capture);
|
||||
gst_v4l2_buffer_pool_enable_resolution_change (GST_V4L2_BUFFER_POOL
|
||||
(cpool));
|
||||
|
||||
/* Ensure our internal pool is activated */
|
||||
active = gst_buffer_pool_set_active (cpool, TRUE);
|
||||
if (cpool)
|
||||
gst_object_unref (cpool);
|
||||
if (!active)
|
||||
goto activate_failed;
|
||||
}
|
||||
|
||||
return GST_FLOW_OK;
|
||||
|
||||
not_negotiated:
|
||||
GST_ERROR_OBJECT (self, "not negotiated");
|
||||
gst_v4l2_error (self, &error);
|
||||
gst_v4l2_object_stop (self->v4l2capture);
|
||||
return GST_FLOW_NOT_NEGOTIATED;
|
||||
activate_failed:
|
||||
GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
|
||||
(_("Failed to allocate required memory.")),
|
||||
("Buffer pool activation failed"));
|
||||
gst_v4l2_object_stop (self->v4l2capture);
|
||||
return GST_FLOW_ERROR;
|
||||
flushing:
|
||||
gst_v4l2_object_stop (self->v4l2capture);
|
||||
return GST_FLOW_FLUSHING;
|
||||
}
|
||||
|
||||
/* Only used initially to wait for a SRC_CH event
|
||||
* called with decoder stream lock */
|
||||
static GstFlowReturn
|
||||
|
@ -751,21 +733,22 @@ gst_v4l2_video_dec_loop (GstVideoDecoder * decoder)
|
|||
}
|
||||
|
||||
GST_DEBUG_OBJECT (decoder, "Setup the capture queue");
|
||||
ret = gst_v4l2_video_dec_setup_capture (decoder);
|
||||
/* FIXME not super nice ? */
|
||||
if (ret == GST_FLOW_FLUSHING || GST_PAD_IS_FLUSHING (decoder->sinkpad)
|
||||
|| GST_PAD_IS_FLUSHING (decoder->srcpad)) {
|
||||
ret = GST_FLOW_FLUSHING;
|
||||
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
|
||||
goto beach;
|
||||
}
|
||||
if (ret != GST_FLOW_OK) {
|
||||
GST_ERROR_OBJECT (decoder, "Failed to setup capture queue");
|
||||
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
|
||||
goto beach;
|
||||
if (G_UNLIKELY (!GST_V4L2_IS_ACTIVE (self->v4l2capture))) {
|
||||
if (!gst_video_decoder_negotiate (decoder)) {
|
||||
/* FIXME not super nice ? */
|
||||
if (GST_PAD_IS_FLUSHING (decoder->sinkpad)
|
||||
|| GST_PAD_IS_FLUSHING (decoder->srcpad)) {
|
||||
ret = GST_FLOW_FLUSHING;
|
||||
} else {
|
||||
ret = GST_FLOW_NOT_NEGOTIATED;
|
||||
GST_ERROR_OBJECT (decoder, "Failed to setup capture queue");
|
||||
}
|
||||
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
|
||||
goto beach;
|
||||
}
|
||||
}
|
||||
|
||||
/* just a safety, as introducing mistakes in setup_capture seems rather
|
||||
/* just a safety, as introducing mistakes in negotiation seems rather
|
||||
* easy.*/
|
||||
g_return_if_fail (GST_V4L2_IS_ACTIVE (self->v4l2capture));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue