mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 00:36:51 +00:00
v4l2codecs: dynamically discovers supported pixels formats
If the driver allows it, for each stateless decoder, enumerate all the pixels formats and use this list for source pad instead of a static template. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7686>
This commit is contained in:
parent
3a52cbcc67
commit
451b32574f
9 changed files with 108 additions and 41 deletions
|
@ -62,11 +62,6 @@ GST_STATIC_PAD_TEMPLATE (GST_VIDEO_DECODER_SINK_NAME,
|
|||
static GstStaticCaps static_src_caps = GST_STATIC_CAPS (SRC_CAPS);
|
||||
static GstStaticCaps static_src_caps_no_drm = GST_STATIC_CAPS (SRC_CAPS_NO_DRM);
|
||||
|
||||
static GstStaticPadTemplate src_template =
|
||||
GST_STATIC_PAD_TEMPLATE (GST_VIDEO_DECODER_SRC_NAME,
|
||||
GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (SRC_CAPS));
|
||||
|
||||
struct _GstV4l2CodecAV1Dec
|
||||
{
|
||||
GstAV1Decoder parent;
|
||||
|
@ -1537,7 +1532,9 @@ gst_v4l2_codec_av1_dec_subclass_init (GstV4l2CodecAV1DecClass * klass,
|
|||
"Daniel Almeida <daniel.almeida@collabora.com>");
|
||||
|
||||
gst_element_class_add_static_pad_template (element_class, &sink_template);
|
||||
gst_element_class_add_static_pad_template (element_class, &src_template);
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||
device->src_caps));
|
||||
|
||||
element_class->change_state =
|
||||
GST_DEBUG_FUNCPTR (gst_v4l2_codec_av1_dec_change_state);
|
||||
|
@ -1608,6 +1605,7 @@ gst_v4l2_codec_av1_dec_register (GstPlugin * plugin, GstV4l2Decoder * decoder,
|
|||
320, 240, 8))
|
||||
return;
|
||||
|
||||
/* Make sure that decoder support stateless AV1 */
|
||||
src_caps = gst_v4l2_decoder_enum_src_formats (decoder, &static_src_caps);
|
||||
|
||||
if (gst_caps_is_empty (src_caps)) {
|
||||
|
@ -1616,6 +1614,10 @@ gst_v4l2_codec_av1_dec_register (GstPlugin * plugin, GstV4l2Decoder * decoder,
|
|||
goto done;
|
||||
}
|
||||
|
||||
/* Get all supported pixel formats for AV1 */
|
||||
device->src_caps =
|
||||
gst_v4l2_decoder_enum_all_src_formats (decoder, &static_src_caps);
|
||||
|
||||
/* TODO uncomment this when AV1 get included in Linus tree */
|
||||
#if 0
|
||||
version = gst_v4l2_decoder_get_version (decoder);
|
||||
|
|
|
@ -34,6 +34,7 @@ typedef struct {
|
|||
guint32 function;
|
||||
gchar *media_device_path;
|
||||
gchar *video_device_path;
|
||||
GstCaps *src_caps;
|
||||
} GstV4l2CodecDevice;
|
||||
|
||||
GType gst_v4l2_codec_device_get_type (void);
|
||||
|
|
|
@ -60,11 +60,6 @@ GST_STATIC_PAD_TEMPLATE (GST_VIDEO_DECODER_SINK_NAME,
|
|||
static GstStaticCaps static_src_caps = GST_STATIC_CAPS (SRC_CAPS);
|
||||
static GstStaticCaps static_src_caps_no_drm = GST_STATIC_CAPS (SRC_CAPS_NO_DRM);
|
||||
|
||||
static GstStaticPadTemplate src_template =
|
||||
GST_STATIC_PAD_TEMPLATE (GST_VIDEO_DECODER_SRC_NAME,
|
||||
GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (SRC_CAPS));
|
||||
|
||||
struct _GstV4l2CodecH264Dec
|
||||
{
|
||||
GstH264Decoder parent;
|
||||
|
@ -1554,7 +1549,10 @@ gst_v4l2_codec_h264_dec_subclass_init (GstV4l2CodecH264DecClass * klass,
|
|||
"Nicolas Dufresne <nicolas.dufresne@collabora.com>");
|
||||
|
||||
gst_element_class_add_static_pad_template (element_class, &sink_template);
|
||||
gst_element_class_add_static_pad_template (element_class, &src_template);
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||
device->src_caps));
|
||||
|
||||
element_class->change_state =
|
||||
GST_DEBUG_FUNCPTR (gst_v4l2_codec_h264_dec_change_state);
|
||||
|
||||
|
@ -1601,6 +1599,8 @@ gst_v4l2_codec_h264_dec_register (GstPlugin * plugin, GstV4l2Decoder * decoder,
|
|||
if (!gst_v4l2_decoder_set_sink_fmt (decoder, V4L2_PIX_FMT_H264_SLICE,
|
||||
320, 240, 8))
|
||||
return;
|
||||
|
||||
/* Make sure that decoder support stateless H264 */
|
||||
src_caps = gst_v4l2_decoder_enum_src_formats (decoder, &static_src_caps);
|
||||
|
||||
if (gst_caps_is_empty (src_caps)) {
|
||||
|
@ -1609,6 +1609,10 @@ gst_v4l2_codec_h264_dec_register (GstPlugin * plugin, GstV4l2Decoder * decoder,
|
|||
goto done;
|
||||
}
|
||||
|
||||
/* Get all supported pixel formats for H264 */
|
||||
device->src_caps =
|
||||
gst_v4l2_decoder_enum_all_src_formats (decoder, &static_src_caps);
|
||||
|
||||
version = gst_v4l2_decoder_get_version (decoder);
|
||||
if (version < V4L2_MIN_KERNEL_VERSION)
|
||||
GST_WARNING ("V4L2 API v%u.%u too old, at least v%u.%u required",
|
||||
|
|
|
@ -61,11 +61,6 @@ GST_STATIC_PAD_TEMPLATE (GST_VIDEO_DECODER_SINK_NAME,
|
|||
static GstStaticCaps static_src_caps = GST_STATIC_CAPS (SRC_CAPS);
|
||||
static GstStaticCaps static_src_caps_no_drm = GST_STATIC_CAPS (SRC_CAPS_NO_DRM);
|
||||
|
||||
static GstStaticPadTemplate src_template =
|
||||
GST_STATIC_PAD_TEMPLATE (GST_VIDEO_DECODER_SRC_NAME,
|
||||
GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (SRC_CAPS));
|
||||
|
||||
struct _GstV4l2CodecH265Dec
|
||||
{
|
||||
GstH265Decoder parent;
|
||||
|
@ -1687,7 +1682,10 @@ gst_v4l2_codec_h265_dec_subclass_init (GstV4l2CodecH265DecClass * klass,
|
|||
"Nicolas Dufresne <nicolas.dufresne@collabora.com>");
|
||||
|
||||
gst_element_class_add_static_pad_template (element_class, &sink_template);
|
||||
gst_element_class_add_static_pad_template (element_class, &src_template);
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||
device->src_caps));
|
||||
|
||||
element_class->change_state =
|
||||
GST_DEBUG_FUNCPTR (gst_v4l2_codec_h265_dec_change_state);
|
||||
|
||||
|
@ -1732,6 +1730,8 @@ gst_v4l2_codec_h265_dec_register (GstPlugin * plugin, GstV4l2Decoder * decoder,
|
|||
if (!gst_v4l2_decoder_set_sink_fmt (decoder, V4L2_PIX_FMT_HEVC_SLICE,
|
||||
320, 240, 8))
|
||||
return;
|
||||
|
||||
/* Make sure that decoder support stateless H265 */
|
||||
src_caps = gst_v4l2_decoder_enum_src_formats (decoder, &static_src_caps);
|
||||
|
||||
if (gst_caps_is_empty (src_caps)) {
|
||||
|
@ -1740,6 +1740,10 @@ gst_v4l2_codec_h265_dec_register (GstPlugin * plugin, GstV4l2Decoder * decoder,
|
|||
goto done;
|
||||
}
|
||||
|
||||
/* Get all supported pixel formats for H265 */
|
||||
device->src_caps =
|
||||
gst_v4l2_decoder_enum_all_src_formats (decoder, &static_src_caps);
|
||||
|
||||
version = gst_v4l2_decoder_get_version (decoder);
|
||||
if (version < V4L2_MIN_KERNEL_VERSION)
|
||||
GST_WARNING ("V4L2 API v%u.%u too old, at least v%u.%u required",
|
||||
|
|
|
@ -63,11 +63,6 @@ GST_STATIC_PAD_TEMPLATE (GST_VIDEO_DECODER_SINK_NAME,
|
|||
static GstStaticCaps static_src_caps = GST_STATIC_CAPS (SRC_CAPS);
|
||||
static GstStaticCaps static_src_caps_no_drm = GST_STATIC_CAPS (SRC_CAPS_NO_DRM);
|
||||
|
||||
static GstStaticPadTemplate src_template =
|
||||
GST_STATIC_PAD_TEMPLATE (GST_VIDEO_DECODER_SRC_NAME,
|
||||
GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (SRC_CAPS));
|
||||
|
||||
struct _GstV4l2CodecMpeg2Dec
|
||||
{
|
||||
GstMpeg2Decoder parent;
|
||||
|
@ -1074,7 +1069,10 @@ gst_v4l2_codec_mpeg2_dec_subclass_init (GstV4l2CodecMpeg2DecClass * klass,
|
|||
"Daniel Almeida <daniel.almeida@collabora.com>");
|
||||
|
||||
gst_element_class_add_static_pad_template (element_class, &sink_template);
|
||||
gst_element_class_add_static_pad_template (element_class, &src_template);
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||
device->src_caps));
|
||||
|
||||
element_class->change_state =
|
||||
GST_DEBUG_FUNCPTR (gst_v4l2_codec_mpeg2_dec_change_state);
|
||||
|
||||
|
@ -1118,6 +1116,8 @@ gst_v4l2_codec_mpeg2_dec_register (GstPlugin * plugin, GstV4l2Decoder * decoder,
|
|||
if (!gst_v4l2_decoder_set_sink_fmt (decoder, V4L2_PIX_FMT_MPEG2_SLICE,
|
||||
320, 240, 8))
|
||||
return;
|
||||
|
||||
/* Make sure that decoder support stateless MPEG2 */
|
||||
src_caps = gst_v4l2_decoder_enum_src_formats (decoder, &static_src_caps);
|
||||
|
||||
if (gst_caps_is_empty (src_caps)) {
|
||||
|
@ -1126,6 +1126,10 @@ gst_v4l2_codec_mpeg2_dec_register (GstPlugin * plugin, GstV4l2Decoder * decoder,
|
|||
goto done;
|
||||
}
|
||||
|
||||
/* Get all supported pixel formats for MPEG2 */
|
||||
device->src_caps =
|
||||
gst_v4l2_decoder_enum_all_src_formats (decoder, &static_src_caps);
|
||||
|
||||
gst_v4l2_decoder_register (plugin, GST_TYPE_V4L2_CODEC_MPEG2_DEC,
|
||||
(GClassInitFunc) gst_v4l2_codec_mpeg2_dec_subclass_init,
|
||||
gst_mini_object_ref (GST_MINI_OBJECT (device)),
|
||||
|
|
|
@ -64,11 +64,6 @@ GST_STATIC_PAD_TEMPLATE (GST_VIDEO_DECODER_SINK_NAME,
|
|||
static GstStaticCaps static_src_caps = GST_STATIC_CAPS (SRC_CAPS);
|
||||
static GstStaticCaps static_src_caps_no_drm = GST_STATIC_CAPS (SRC_CAPS_NO_DRM);
|
||||
|
||||
static GstStaticPadTemplate src_template =
|
||||
GST_STATIC_PAD_TEMPLATE (GST_VIDEO_DECODER_SRC_NAME,
|
||||
GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (SRC_CAPS));
|
||||
|
||||
struct _GstV4l2CodecVp8Dec
|
||||
{
|
||||
GstVp8Decoder parent;
|
||||
|
@ -934,7 +929,10 @@ gst_v4l2_codec_vp8_dec_subclass_init (GstV4l2CodecVp8DecClass * klass,
|
|||
"Nicolas Dufresne <nicolas.dufresne@collabora.com>");
|
||||
|
||||
gst_element_class_add_static_pad_template (element_class, &sink_template);
|
||||
gst_element_class_add_static_pad_template (element_class, &src_template);
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||
device->src_caps));
|
||||
|
||||
element_class->change_state =
|
||||
GST_DEBUG_FUNCPTR (gst_v4l2_codec_vp8_dec_change_state);
|
||||
|
||||
|
@ -995,6 +993,8 @@ gst_v4l2_codec_vp8_dec_register (GstPlugin * plugin, GstV4l2Decoder * decoder,
|
|||
if (!gst_v4l2_decoder_set_sink_fmt (decoder, V4L2_PIX_FMT_VP8_FRAME,
|
||||
320, 240, 8))
|
||||
return;
|
||||
|
||||
/* Make sure that decoder support stateless VP8 */
|
||||
src_caps = gst_v4l2_decoder_enum_src_formats (decoder, &static_src_caps);
|
||||
|
||||
if (gst_caps_is_empty (src_caps)) {
|
||||
|
@ -1003,6 +1003,10 @@ gst_v4l2_codec_vp8_dec_register (GstPlugin * plugin, GstV4l2Decoder * decoder,
|
|||
goto done;
|
||||
}
|
||||
|
||||
/* Get all supported pixel formats for VP8 */
|
||||
device->src_caps =
|
||||
gst_v4l2_decoder_enum_all_src_formats (decoder, &static_src_caps);
|
||||
|
||||
gst_v4l2_decoder_register (plugin, GST_TYPE_V4L2_CODEC_VP8_DEC,
|
||||
(GClassInitFunc) gst_v4l2_codec_vp8_dec_subclass_init,
|
||||
gst_mini_object_ref (GST_MINI_OBJECT (device)),
|
||||
|
@ -1014,7 +1018,7 @@ gst_v4l2_codec_vp8_dec_register (GstPlugin * plugin, GstV4l2Decoder * decoder,
|
|||
|
||||
alpha_caps = gst_caps_from_string ("video/x-raw,format={I420, NV12}");
|
||||
|
||||
if (gst_caps_can_intersect (src_caps, alpha_caps))
|
||||
if (gst_caps_can_intersect (device->src_caps, alpha_caps))
|
||||
gst_v4l2_codec_alpha_decode_bin_register (plugin,
|
||||
(GClassInitFunc) gst_v4l2_codec_vp8_alpha_decode_bin_subclass_init,
|
||||
element_name, "v4l2slvp8%salphadecodebin", device, rank);
|
||||
|
|
|
@ -65,11 +65,6 @@ GST_STATIC_PAD_TEMPLATE (GST_VIDEO_DECODER_SINK_NAME,
|
|||
static GstStaticCaps static_src_caps = GST_STATIC_CAPS (SRC_CAPS);
|
||||
static GstStaticCaps static_src_caps_no_drm = GST_STATIC_CAPS (SRC_CAPS_NO_DRM);
|
||||
|
||||
static GstStaticPadTemplate src_template =
|
||||
GST_STATIC_PAD_TEMPLATE (GST_VIDEO_DECODER_SRC_NAME,
|
||||
GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS (SRC_CAPS));
|
||||
|
||||
struct _GstV4l2CodecVp9Dec
|
||||
{
|
||||
GstVp9Decoder parent;
|
||||
|
@ -1210,7 +1205,10 @@ gst_v4l2_codec_vp9_dec_subclass_init (GstV4l2CodecVp9DecClass * klass,
|
|||
"Daniel Almeida <daniel.almeida@collabora.com>");
|
||||
|
||||
gst_element_class_add_static_pad_template (element_class, &sink_template);
|
||||
gst_element_class_add_static_pad_template (element_class, &src_template);
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||
device->src_caps));
|
||||
|
||||
element_class->change_state =
|
||||
GST_DEBUG_FUNCPTR (gst_v4l2_codec_vp9_dec_change_state);
|
||||
|
||||
|
@ -1275,6 +1273,8 @@ gst_v4l2_codec_vp9_dec_register (GstPlugin * plugin, GstV4l2Decoder * decoder,
|
|||
if (!gst_v4l2_decoder_set_sink_fmt (decoder, V4L2_PIX_FMT_VP9_FRAME,
|
||||
320, 240, 8))
|
||||
return;
|
||||
|
||||
/* Make sure that decoder support stateless VP9 */
|
||||
src_caps = gst_v4l2_decoder_enum_src_formats (decoder, &static_src_caps);
|
||||
|
||||
if (gst_caps_is_empty (src_caps)) {
|
||||
|
@ -1283,6 +1283,10 @@ gst_v4l2_codec_vp9_dec_register (GstPlugin * plugin, GstV4l2Decoder * decoder,
|
|||
goto done;
|
||||
}
|
||||
|
||||
/* Get all supported pixel formats for VP9 */
|
||||
device->src_caps =
|
||||
gst_v4l2_decoder_enum_all_src_formats (decoder, &static_src_caps);
|
||||
|
||||
gst_v4l2_decoder_register (plugin, GST_TYPE_V4L2_CODEC_VP9_DEC,
|
||||
(GClassInitFunc) gst_v4l2_codec_vp9_dec_subclass_init,
|
||||
gst_mini_object_ref (GST_MINI_OBJECT (device)),
|
||||
|
@ -1294,7 +1298,7 @@ gst_v4l2_codec_vp9_dec_register (GstPlugin * plugin, GstV4l2Decoder * decoder,
|
|||
|
||||
alpha_caps = gst_caps_from_string ("video/x-raw,format={I420, NV12}");
|
||||
|
||||
if (gst_caps_can_intersect (src_caps, alpha_caps))
|
||||
if (gst_caps_can_intersect (device->src_caps, alpha_caps))
|
||||
gst_v4l2_codec_alpha_decode_bin_register (plugin,
|
||||
(GClassInitFunc) gst_v4l2_codec_vp9_alpha_decode_bin_subclass_init,
|
||||
element_name, "v4l2slvp9%salphadecodebin", device, rank);
|
||||
|
|
|
@ -41,6 +41,12 @@
|
|||
GST_DEBUG_CATEGORY (v4l2_decoder_debug);
|
||||
#define GST_CAT_DEFAULT v4l2_decoder_debug
|
||||
|
||||
#define SRC_CAPS \
|
||||
GST_VIDEO_DMA_DRM_CAPS_MAKE " ; " \
|
||||
GST_VIDEO_CAPS_MAKE (GST_V4L2_DEFAULT_VIDEO_FORMATS)
|
||||
|
||||
static GstStaticCaps default_src_caps = GST_STATIC_CAPS (SRC_CAPS);
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
@ -499,9 +505,9 @@ filter_non_dmabuf_caps (GstCapsFeatures * features,
|
|||
return !gst_caps_features_contains (features, GST_CAPS_FEATURE_MEMORY_DMABUF);
|
||||
}
|
||||
|
||||
GstCaps *
|
||||
gst_v4l2_decoder_enum_src_formats (GstV4l2Decoder * self,
|
||||
GstStaticCaps * static_filter)
|
||||
static GstCaps *
|
||||
gst_v4l2_decoder_enum_src_formats_full (GstV4l2Decoder * self,
|
||||
GstStaticCaps * static_filter, gboolean enum_all)
|
||||
{
|
||||
gint ret;
|
||||
struct v4l2_format fmt = {
|
||||
|
@ -527,7 +533,17 @@ gst_v4l2_decoder_enum_src_formats (GstV4l2Decoder * self,
|
|||
for (i = 0; ret >= 0; i++) {
|
||||
struct v4l2_fmtdesc fmtdesc = { i, self->src_buf_type, };
|
||||
|
||||
if (enum_all)
|
||||
fmtdesc.index |= V4L2_FMTDESC_FLAG_ENUM_ALL;
|
||||
|
||||
ret = ioctl (self->video_fd, VIDIOC_ENUM_FMT, &fmtdesc);
|
||||
/* If the driver can't enumerate all the pixels formats
|
||||
* return empty caps */
|
||||
if (enum_all && ret == -EINVAL) {
|
||||
gst_caps_unref (caps);
|
||||
return gst_static_caps_get (&default_src_caps);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
if (errno != EINVAL)
|
||||
GST_ERROR_OBJECT (self, "VIDIOC_ENUM_FMT failed: %s",
|
||||
|
@ -551,11 +567,36 @@ gst_v4l2_decoder_enum_src_formats (GstV4l2Decoder * self,
|
|||
gst_caps_filter_and_map_in_place (tmp, filter_non_dmabuf_caps, NULL);
|
||||
gst_caps_append (caps, tmp);
|
||||
|
||||
if (enum_all) {
|
||||
/* When enumerating all the formats we don't need yet resolution
|
||||
* so remove width, height and framerate fields */
|
||||
guint n = gst_caps_get_size (caps);
|
||||
for (i = 0; i < n; i++) {
|
||||
GstStructure *s = gst_caps_get_structure (caps, i);
|
||||
|
||||
gst_structure_remove_fields (s, "width", "height", "framerate", NULL);
|
||||
}
|
||||
caps = gst_caps_simplify (caps);
|
||||
}
|
||||
GST_DEBUG_OBJECT (self, "Probed caps: %" GST_PTR_FORMAT, caps);
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
||||
GstCaps *
|
||||
gst_v4l2_decoder_enum_src_formats (GstV4l2Decoder * self,
|
||||
GstStaticCaps * static_filter)
|
||||
{
|
||||
return gst_v4l2_decoder_enum_src_formats_full (self, static_filter, FALSE);
|
||||
}
|
||||
|
||||
GstCaps *
|
||||
gst_v4l2_decoder_enum_all_src_formats (GstV4l2Decoder * self,
|
||||
GstStaticCaps * static_filter)
|
||||
{
|
||||
return gst_v4l2_decoder_enum_src_formats_full (self, static_filter, TRUE);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_v4l2_decoder_remove_buffers (GstV4l2Decoder * self,
|
||||
GstPadDirection direction, guint index, guint num_buffers)
|
||||
|
|
|
@ -70,6 +70,9 @@ gboolean gst_v4l2_decoder_set_sink_fmt (GstV4l2Decoder * self, guint32
|
|||
GstCaps * gst_v4l2_decoder_enum_src_formats (GstV4l2Decoder * self,
|
||||
GstStaticCaps * static_filter);
|
||||
|
||||
GstCaps * gst_v4l2_decoder_enum_all_src_formats (GstV4l2Decoder * self,
|
||||
GstStaticCaps * static_filter);
|
||||
|
||||
gboolean gst_v4l2_decoder_select_src_format (GstV4l2Decoder * self,
|
||||
GstCaps * caps,
|
||||
GstVideoInfo * vinfo,
|
||||
|
|
Loading…
Reference in a new issue