v4l2codecs: decoders: Add DMA_DRM caps support

In order to simplify caps negotiations for clients and, notably, be more
compatible with va* decoders.
Crucially this allows clients to know ahead of time whether buffers will
actually be DMABufs.

Similar to GstVaBaseDec we only announce system memory caps if the peer
has ANY caps. Further more, and again like va decoders, we fail in
`decide_allocation()` if DMA_DRM caps are used without VideoMeta.
Apart from buggy peers this can happen e.g. when a peer with ANY caps
is used in combination with caps filters.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6376>
This commit is contained in:
Robert Mader 2024-01-06 13:07:16 +01:00 committed by GStreamer Marge Bot
parent 383545d856
commit aef872944e
8 changed files with 271 additions and 42 deletions

View file

@ -53,9 +53,14 @@ GST_STATIC_PAD_TEMPLATE (GST_VIDEO_DECODER_SINK_NAME,
GST_STATIC_CAPS ("video/x-av1, alignment=frame"));
#define SRC_CAPS \
GST_VIDEO_DMA_DRM_CAPS_MAKE " ; " \
GST_VIDEO_CAPS_MAKE (GST_V4L2_DEFAULT_VIDEO_FORMATS)
#define SRC_CAPS_NO_DRM \
GST_VIDEO_CAPS_MAKE (GST_V4L2_DEFAULT_VIDEO_FORMATS)
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,
@ -68,6 +73,7 @@ struct _GstV4l2CodecAV1Dec
GstV4l2Decoder *decoder;
GstVideoCodecState *output_state;
GstVideoInfo vinfo;
GstVideoInfoDmaDrm vinfo_drm;
GstV4l2CodecAllocator *sink_allocator;
GstV4l2CodecAllocator *src_allocator;
@ -283,7 +289,9 @@ gst_v4l2_codec_av1_dec_negotiate (GstVideoDecoder * decoder)
};
/* *INDENT-ON* */
GstCaps *filter, *caps;
GstCaps *peer_caps, *filter, *caps;
GstStaticCaps *static_filter;
/* Ignore downstream renegotiation request. */
if (self->streaming)
goto done;
@ -308,7 +316,13 @@ gst_v4l2_codec_av1_dec_negotiate (GstVideoDecoder * decoder)
return FALSE;
}
filter = gst_v4l2_decoder_enum_src_formats (self->decoder, &static_src_caps);
/* If the peer has ANY caps only advertise system memory caps */
peer_caps = gst_pad_peer_query_caps (decoder->srcpad, NULL);
static_filter =
gst_caps_is_any (peer_caps) ? &static_src_caps_no_drm : &static_src_caps;
gst_caps_unref (peer_caps);
filter = gst_v4l2_decoder_enum_src_formats (self->decoder, static_filter);
if (!filter) {
GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
("No supported decoder output formats"), (NULL));
@ -320,7 +334,8 @@ gst_v4l2_codec_av1_dec_negotiate (GstVideoDecoder * decoder)
gst_caps_unref (filter);
GST_DEBUG_OBJECT (self, "Peer supported formats: %" GST_PTR_FORMAT, caps);
if (!gst_v4l2_decoder_select_src_format (self->decoder, caps, &self->vinfo)) {
if (!gst_v4l2_decoder_select_src_format (self->decoder, caps, &self->vinfo,
&self->vinfo_drm)) {
GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
("Unsupported pixel format"),
("No support for %ux%u", self->frame_width, self->frame_height));
@ -335,7 +350,8 @@ done:
self->output_state =
gst_v4l2_decoder_set_output_state (GST_VIDEO_DECODER (self), &self->vinfo,
self->render_width, self->render_height, av1dec->input_state);
&self->vinfo_drm, self->render_width, self->render_height,
av1dec->input_state);
if (GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder)) {
if (self->streaming)
@ -368,6 +384,7 @@ gst_v4l2_codec_av1_dec_decide_allocation (GstVideoDecoder * decoder,
GstQuery * query)
{
GstV4l2CodecAV1Dec *self = GST_V4L2_CODEC_AV1_DEC (decoder);
GstCaps *caps = NULL;
guint min = 0, num_bitstream;
/* If we are streaming here, then it means there is nothing allocation
@ -375,11 +392,24 @@ gst_v4l2_codec_av1_dec_decide_allocation (GstVideoDecoder * decoder,
if (self->streaming)
goto no_internal_changes;
g_clear_object (&self->src_pool);
g_clear_object (&self->src_allocator);
self->has_videometa = gst_query_find_allocation_meta (query,
GST_VIDEO_META_API_TYPE, NULL);
g_clear_object (&self->src_pool);
g_clear_object (&self->src_allocator);
gst_query_parse_allocation (query, &caps, NULL);
if (!caps) {
GST_ERROR_OBJECT (self, "No valid caps");
return FALSE;
}
if (gst_video_is_dma_drm_caps (caps) && !self->has_videometa) {
GST_ERROR_OBJECT (self,
"DMABuf caps negotiated without the mandatory support of VideoMeta");
return FALSE;
}
gst_caps_unref (caps);
if (gst_query_get_n_allocation_pools (query) > 0)
gst_query_parse_nth_allocation_pool (query, 0, NULL, NULL, &min, NULL);
@ -1551,6 +1581,7 @@ gst_v4l2_codec_av1_dec_subinit (GstV4l2CodecAV1Dec * self,
{
self->decoder = gst_v4l2_decoder_new (klass->device);
gst_video_info_init (&self->vinfo);
gst_video_info_dma_drm_init (&self->vinfo_drm);
self->tile_group_entries =
g_array_new (FALSE, TRUE, sizeof (struct v4l2_ctrl_av1_tile_group_entry));
}

View file

@ -51,9 +51,14 @@ GST_STATIC_PAD_TEMPLATE (GST_VIDEO_DECODER_SINK_NAME,
);
#define SRC_CAPS \
GST_VIDEO_DMA_DRM_CAPS_MAKE " ; " \
GST_VIDEO_CAPS_MAKE (GST_V4L2_DEFAULT_VIDEO_FORMATS)
#define SRC_CAPS_NO_DRM \
GST_VIDEO_CAPS_MAKE (GST_V4L2_DEFAULT_VIDEO_FORMATS)
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,
@ -66,6 +71,7 @@ struct _GstV4l2CodecH264Dec
GstV4l2Decoder *decoder;
GstVideoCodecState *output_state;
GstVideoInfo vinfo;
GstVideoInfoDmaDrm vinfo_drm;
gint display_width;
gint display_height;
gint coded_width;
@ -324,7 +330,8 @@ gst_v4l2_codec_h264_dec_negotiate (GstVideoDecoder * decoder)
},
};
/* *INDENT-ON* */
GstCaps *filter, *caps;
GstCaps *peer_caps, *filter, *caps;
GstStaticCaps *static_filter;
/* Ignore downstream renegotiation request. */
if (self->streaming)
@ -350,7 +357,13 @@ gst_v4l2_codec_h264_dec_negotiate (GstVideoDecoder * decoder)
return FALSE;
}
filter = gst_v4l2_decoder_enum_src_formats (self->decoder, &static_src_caps);
/* If the peer has ANY caps only advertise system memory caps */
peer_caps = gst_pad_peer_query_caps (decoder->srcpad, NULL);
static_filter =
gst_caps_is_any (peer_caps) ? &static_src_caps_no_drm : &static_src_caps;
gst_caps_unref (peer_caps);
filter = gst_v4l2_decoder_enum_src_formats (self->decoder, static_filter);
if (!filter) {
GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
("No supported decoder output formats"), (NULL));
@ -362,7 +375,8 @@ gst_v4l2_codec_h264_dec_negotiate (GstVideoDecoder * decoder)
gst_caps_unref (filter);
GST_DEBUG_OBJECT (self, "Peer supported formats: %" GST_PTR_FORMAT, caps);
if (!gst_v4l2_decoder_select_src_format (self->decoder, caps, &self->vinfo)) {
if (!gst_v4l2_decoder_select_src_format (self->decoder, caps, &self->vinfo,
&self->vinfo_drm)) {
GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
("Unsupported bitdepth/chroma format"),
("No support for %ux%u %ubit chroma IDC %i", self->coded_width,
@ -378,7 +392,8 @@ done:
self->output_state =
gst_v4l2_decoder_set_output_state (GST_VIDEO_DECODER (self), &self->vinfo,
self->display_width, self->display_height, h264dec->input_state);
&self->vinfo_drm, self->display_width, self->display_height,
h264dec->input_state);
if (self->interlaced)
self->output_state->info.interlace_mode = GST_VIDEO_INTERLACE_MODE_MIXED;
@ -414,6 +429,7 @@ gst_v4l2_codec_h264_dec_decide_allocation (GstVideoDecoder * decoder,
GstQuery * query)
{
GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder);
GstCaps *caps = NULL;
guint min = 0, num_bitstream;
/* If we are streaming here, then it means there is nothing allocation
@ -421,11 +437,24 @@ gst_v4l2_codec_h264_dec_decide_allocation (GstVideoDecoder * decoder,
if (self->streaming)
goto no_internal_changes;
g_clear_object (&self->src_pool);
g_clear_object (&self->src_allocator);
self->has_videometa = gst_query_find_allocation_meta (query,
GST_VIDEO_META_API_TYPE, NULL);
g_clear_object (&self->src_pool);
g_clear_object (&self->src_allocator);
gst_query_parse_allocation (query, &caps, NULL);
if (!caps) {
GST_ERROR_OBJECT (self, "No valid caps");
return FALSE;
}
if (gst_video_is_dma_drm_caps (caps) && !self->has_videometa) {
GST_ERROR_OBJECT (self,
"DMABuf caps negotiated without the mandatory support of VideoMeta");
return FALSE;
}
gst_caps_unref (caps);
if (gst_query_get_n_allocation_pools (query) > 0)
gst_query_parse_nth_allocation_pool (query, 0, NULL, NULL, &min, NULL);
@ -1484,6 +1513,7 @@ gst_v4l2_codec_h264_dec_subinit (GstV4l2CodecH264Dec * self,
{
self->decoder = gst_v4l2_decoder_new (klass->device);
gst_video_info_init (&self->vinfo);
gst_video_info_dma_drm_init (&self->vinfo_drm);
self->slice_params = g_array_sized_new (FALSE, TRUE,
sizeof (struct v4l2_ctrl_h264_slice_params), 4);
g_array_set_size (self->slice_params, 4);

View file

@ -52,9 +52,14 @@ GST_STATIC_PAD_TEMPLATE (GST_VIDEO_DECODER_SINK_NAME,
);
#define SRC_CAPS \
GST_VIDEO_DMA_DRM_CAPS_MAKE " ; " \
GST_VIDEO_CAPS_MAKE (GST_V4L2_DEFAULT_VIDEO_FORMATS)
#define SRC_CAPS_NO_DRM \
GST_VIDEO_CAPS_MAKE (GST_V4L2_DEFAULT_VIDEO_FORMATS)
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,
@ -67,6 +72,7 @@ struct _GstV4l2CodecH265Dec
GstV4l2Decoder *decoder;
GstVideoCodecState *output_state;
GstVideoInfo vinfo;
GstVideoInfoDmaDrm vinfo_drm;
gint display_width;
gint display_height;
gint coded_width;
@ -358,7 +364,8 @@ gst_v4l2_codec_h265_dec_negotiate (GstVideoDecoder * decoder)
},
};
/* *INDENT-ON* */
GstCaps *filter, *caps;
GstCaps *peer_caps, *filter, *caps;
GstStaticCaps *static_filter;
/* Ignore downstream renegotiation request. */
if (self->streaming)
@ -384,7 +391,13 @@ gst_v4l2_codec_h265_dec_negotiate (GstVideoDecoder * decoder)
return FALSE;
}
filter = gst_v4l2_decoder_enum_src_formats (self->decoder, &static_src_caps);
/* If the peer has ANY caps only advertise system memory caps */
peer_caps = gst_pad_peer_query_caps (decoder->srcpad, NULL);
static_filter =
gst_caps_is_any (peer_caps) ? &static_src_caps_no_drm : &static_src_caps;
gst_caps_unref (peer_caps);
filter = gst_v4l2_decoder_enum_src_formats (self->decoder, static_filter);
if (!filter) {
GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
("No supported decoder output formats"), (NULL));
@ -396,7 +409,8 @@ gst_v4l2_codec_h265_dec_negotiate (GstVideoDecoder * decoder)
gst_caps_unref (filter);
GST_DEBUG_OBJECT (self, "Peer supported formats: %" GST_PTR_FORMAT, caps);
if (!gst_v4l2_decoder_select_src_format (self->decoder, caps, &self->vinfo)) {
if (!gst_v4l2_decoder_select_src_format (self->decoder, caps, &self->vinfo,
&self->vinfo_drm)) {
GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
("Unsupported bitdepth/chroma format"),
("No support for %ux%u %ubit chroma IDC %i", self->coded_width,
@ -412,7 +426,8 @@ done:
self->output_state =
gst_v4l2_decoder_set_output_state (GST_VIDEO_DECODER (self), &self->vinfo,
self->display_width, self->display_height, h265dec->input_state);
&self->vinfo_drm, self->display_width, self->display_height,
h265dec->input_state);
if (GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder)) {
if (self->streaming)
@ -445,16 +460,30 @@ gst_v4l2_codec_h265_dec_decide_allocation (GstVideoDecoder * decoder,
GstQuery * query)
{
GstV4l2CodecH265Dec *self = GST_V4L2_CODEC_H265_DEC (decoder);
GstCaps *caps = NULL;
guint min = 0;
if (self->streaming)
goto no_internal_changes;
g_clear_object (&self->src_pool);
g_clear_object (&self->src_allocator);
self->has_videometa = gst_query_find_allocation_meta (query,
GST_VIDEO_META_API_TYPE, NULL);
g_clear_object (&self->src_pool);
g_clear_object (&self->src_allocator);
gst_query_parse_allocation (query, &caps, NULL);
if (!caps) {
GST_ERROR_OBJECT (self, "No valid caps");
return FALSE;
}
if (gst_video_is_dma_drm_caps (caps) && !self->has_videometa) {
GST_ERROR_OBJECT (self,
"DMABuf caps negotiated without the mandatory support of VideoMeta");
return FALSE;
}
gst_caps_unref (caps);
if (gst_query_get_n_allocation_pools (query) > 0)
gst_query_parse_nth_allocation_pool (query, 0, NULL, NULL, &min, NULL);
@ -1598,6 +1627,7 @@ gst_v4l2_codec_h265_dec_subinit (GstV4l2CodecH265Dec * self,
{
self->decoder = gst_v4l2_decoder_new (klass->device);
gst_video_info_init (&self->vinfo);
gst_video_info_dma_drm_init (&self->vinfo_drm);
self->slice_params = g_array_sized_new (FALSE, TRUE,
sizeof (struct v4l2_ctrl_hevc_slice_params), 4);
g_array_set_size (self->slice_params, 4);

View file

@ -54,9 +54,14 @@ GST_STATIC_PAD_TEMPLATE (GST_VIDEO_DECODER_SINK_NAME,
"mpegversion=(int) 2, " "profile=(string) {main, simple} "));
#define SRC_CAPS \
GST_VIDEO_DMA_DRM_CAPS_MAKE " ; " \
GST_VIDEO_CAPS_MAKE (GST_V4L2_DEFAULT_VIDEO_FORMATS)
#define SRC_CAPS_NO_DRM \
GST_VIDEO_CAPS_MAKE (GST_V4L2_DEFAULT_VIDEO_FORMATS)
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,
@ -70,6 +75,7 @@ struct _GstV4l2CodecMpeg2Dec
GstV4l2Decoder *decoder;
GstVideoCodecState *output_state;
GstVideoInfo vinfo;
GstVideoInfoDmaDrm vinfo_drm;
guint16 width;
guint16 height;
@ -246,7 +252,8 @@ gst_v4l2_codec_mpeg2_dec_negotiate (GstVideoDecoder * decoder)
};
/* *INDENT-ON* */
GstCaps *filter, *caps;
GstCaps *peer_caps, *filter, *caps;
GstStaticCaps *static_filter;
/* Ignore downstream renegotiation request. */
if (self->streaming)
@ -272,7 +279,13 @@ gst_v4l2_codec_mpeg2_dec_negotiate (GstVideoDecoder * decoder)
return FALSE;
}
filter = gst_v4l2_decoder_enum_src_formats (self->decoder, &static_src_caps);
/* If the peer has ANY caps only advertise system memory caps */
peer_caps = gst_pad_peer_query_caps (decoder->srcpad, NULL);
static_filter =
gst_caps_is_any (peer_caps) ? &static_src_caps_no_drm : &static_src_caps;
gst_caps_unref (peer_caps);
filter = gst_v4l2_decoder_enum_src_formats (self->decoder, static_filter);
if (!filter) {
GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
("No supported decoder output formats"), (NULL));
@ -284,7 +297,8 @@ gst_v4l2_codec_mpeg2_dec_negotiate (GstVideoDecoder * decoder)
gst_caps_unref (filter);
GST_DEBUG_OBJECT (self, "Peer supported formats: %" GST_PTR_FORMAT, caps);
if (!gst_v4l2_decoder_select_src_format (self->decoder, caps, &self->vinfo)) {
if (!gst_v4l2_decoder_select_src_format (self->decoder, caps, &self->vinfo,
&self->vinfo_drm)) {
GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
("Unsupported bitdepth/chroma format"),
("No support for %ux%u chroma IDC %i", self->width,
@ -300,7 +314,7 @@ done:
self->output_state =
gst_v4l2_decoder_set_output_state (GST_VIDEO_DECODER (self), &self->vinfo,
self->width, self->height, mpeg2dec->input_state);
&self->vinfo_drm, self->width, self->height, mpeg2dec->input_state);
if (self->interlaced)
self->output_state->info.interlace_mode =
@ -337,6 +351,7 @@ gst_v4l2_codec_mpeg2_dec_decide_allocation (GstVideoDecoder * decoder,
GstQuery * query)
{
GstV4l2CodecMpeg2Dec *self = GST_V4L2_CODEC_MPEG2_DEC (decoder);
GstCaps *caps = NULL;
guint min = 0, num_bitstream;
/* If we are streaming here, then it means there is nothing allocation
@ -344,11 +359,24 @@ gst_v4l2_codec_mpeg2_dec_decide_allocation (GstVideoDecoder * decoder,
if (self->streaming)
goto no_internal_changes;
g_clear_object (&self->src_pool);
g_clear_object (&self->src_allocator);
self->has_videometa = gst_query_find_allocation_meta (query,
GST_VIDEO_META_API_TYPE, NULL);
g_clear_object (&self->src_pool);
g_clear_object (&self->src_allocator);
gst_query_parse_allocation (query, &caps, NULL);
if (!caps) {
GST_ERROR_OBJECT (self, "No valid caps");
return FALSE;
}
if (gst_video_is_dma_drm_caps (caps) && !self->has_videometa) {
GST_ERROR_OBJECT (self,
"DMABuf caps negotiated without the mandatory support of VideoMeta");
return FALSE;
}
gst_caps_unref (caps);
if (gst_query_get_n_allocation_pools (query) > 0)
gst_query_parse_nth_allocation_pool (query, 0, NULL, NULL, &min, NULL);
@ -1009,6 +1037,7 @@ gst_v4l2_codec_mpeg2_dec_subinit (GstV4l2CodecMpeg2Dec * self,
{
self->decoder = gst_v4l2_decoder_new (klass->device);
gst_video_info_init (&self->vinfo);
gst_video_info_dma_drm_init (&self->vinfo_drm);
}
static void

View file

@ -55,9 +55,14 @@ GST_STATIC_PAD_TEMPLATE (GST_VIDEO_DECODER_SINK_NAME,
);
#define SRC_CAPS \
GST_VIDEO_DMA_DRM_CAPS_MAKE " ; " \
GST_VIDEO_CAPS_MAKE (GST_V4L2_DEFAULT_VIDEO_FORMATS)
#define SRC_CAPS_NO_DRM \
GST_VIDEO_CAPS_MAKE (GST_V4L2_DEFAULT_VIDEO_FORMATS)
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,
@ -70,6 +75,7 @@ struct _GstV4l2CodecVp8Dec
GstV4l2Decoder *decoder;
GstVideoCodecState *output_state;
GstVideoInfo vinfo;
GstVideoInfoDmaDrm vinfo_drm;
gint width;
gint height;
@ -195,7 +201,8 @@ gst_v4l2_codec_vp8_dec_negotiate (GstVideoDecoder * decoder)
},
};
/* *INDENT-ON* */
GstCaps *filter, *caps;
GstCaps *peer_caps, *filter, *caps;
GstStaticCaps *static_filter;
/* Ignore downstream renegotiation request. */
if (self->streaming)
@ -221,7 +228,13 @@ gst_v4l2_codec_vp8_dec_negotiate (GstVideoDecoder * decoder)
return FALSE;
}
filter = gst_v4l2_decoder_enum_src_formats (self->decoder, &static_src_caps);
/* If the peer has ANY caps only advertise system memory caps */
peer_caps = gst_pad_peer_query_caps (decoder->srcpad, NULL);
static_filter =
gst_caps_is_any (peer_caps) ? &static_src_caps_no_drm : &static_src_caps;
gst_caps_unref (peer_caps);
filter = gst_v4l2_decoder_enum_src_formats (self->decoder, static_filter);
if (!filter) {
GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
("No supported decoder output formats"), (NULL));
@ -233,7 +246,8 @@ gst_v4l2_codec_vp8_dec_negotiate (GstVideoDecoder * decoder)
gst_caps_unref (filter);
GST_DEBUG_OBJECT (self, "Peer supported formats: %" GST_PTR_FORMAT, caps);
if (!gst_v4l2_decoder_select_src_format (self->decoder, caps, &self->vinfo)) {
if (!gst_v4l2_decoder_select_src_format (self->decoder, caps, &self->vinfo,
&self->vinfo_drm)) {
GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
("Unsupported pixel format"),
("No support for %ux%u format %s", self->width, self->height,
@ -249,7 +263,7 @@ done:
self->output_state =
gst_v4l2_decoder_set_output_state (GST_VIDEO_DECODER (self), &self->vinfo,
self->width, self->height, vp8dec->input_state);
&self->vinfo_drm, self->width, self->height, vp8dec->input_state);
if (GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder)) {
if (self->streaming)
@ -282,17 +296,31 @@ gst_v4l2_codec_vp8_dec_decide_allocation (GstVideoDecoder * decoder,
GstQuery * query)
{
GstV4l2CodecVp8Dec *self = GST_V4L2_CODEC_VP8_DEC (decoder);
GstCaps *caps = NULL;
guint min = 0;
guint num_bitstream;
if (self->streaming)
goto no_internal_changes;
g_clear_object (&self->src_pool);
g_clear_object (&self->src_allocator);
self->has_videometa = gst_query_find_allocation_meta (query,
GST_VIDEO_META_API_TYPE, NULL);
g_clear_object (&self->src_pool);
g_clear_object (&self->src_allocator);
gst_query_parse_allocation (query, &caps, NULL);
if (!caps) {
GST_ERROR_OBJECT (self, "No valid caps");
return FALSE;
}
if (gst_video_is_dma_drm_caps (caps) && !self->has_videometa) {
GST_ERROR_OBJECT (self,
"DMABuf caps negotiated without the mandatory support of VideoMeta");
return FALSE;
}
gst_caps_unref (caps);
if (gst_query_get_n_allocation_pools (query) > 0)
gst_query_parse_nth_allocation_pool (query, 0, NULL, NULL, &min, NULL);
@ -869,6 +897,7 @@ gst_v4l2_codec_vp8_dec_subinit (GstV4l2CodecVp8Dec * self,
{
self->decoder = gst_v4l2_decoder_new (klass->device);
gst_video_info_init (&self->vinfo);
gst_video_info_dma_drm_init (&self->vinfo_drm);
}
static void

View file

@ -56,9 +56,14 @@ GST_STATIC_PAD_TEMPLATE (GST_VIDEO_DECODER_SINK_NAME,
);
#define SRC_CAPS \
GST_VIDEO_DMA_DRM_CAPS_MAKE " ; " \
GST_VIDEO_CAPS_MAKE (GST_V4L2_DEFAULT_VIDEO_FORMATS)
#define SRC_CAPS_NO_DRM \
GST_VIDEO_CAPS_MAKE (GST_V4L2_DEFAULT_VIDEO_FORMATS)
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,
@ -71,6 +76,7 @@ struct _GstV4l2CodecVp9Dec
GstV4l2Decoder *decoder;
GstVideoCodecState *output_state;
GstVideoInfo vinfo;
GstVideoInfoDmaDrm vinfo_drm;
gint width;
gint height;
@ -467,7 +473,9 @@ gst_v4l2_codec_vp9_dec_negotiate (GstVideoDecoder * decoder)
};
/* *INDENT-ON* */
GstCaps *filter, *caps;
GstCaps *peer_caps, *filter, *caps;
GstStaticCaps *static_filter;
/* Ignore downstream renegotiation request. */
if (self->streaming)
goto done;
@ -491,7 +499,13 @@ gst_v4l2_codec_vp9_dec_negotiate (GstVideoDecoder * decoder)
return FALSE;
}
filter = gst_v4l2_decoder_enum_src_formats (self->decoder, &static_src_caps);
/* If the peer has ANY caps only advertise system memory caps */
peer_caps = gst_pad_peer_query_caps (decoder->srcpad, NULL);
static_filter =
gst_caps_is_any (peer_caps) ? &static_src_caps_no_drm : &static_src_caps;
gst_caps_unref (peer_caps);
filter = gst_v4l2_decoder_enum_src_formats (self->decoder, static_filter);
if (!filter) {
GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
("No supported decoder output formats"), (NULL));
@ -503,7 +517,8 @@ gst_v4l2_codec_vp9_dec_negotiate (GstVideoDecoder * decoder)
gst_caps_unref (filter);
GST_DEBUG_OBJECT (self, "Peer supported formats: %" GST_PTR_FORMAT, caps);
if (!gst_v4l2_decoder_select_src_format (self->decoder, caps, &self->vinfo)) {
if (!gst_v4l2_decoder_select_src_format (self->decoder, caps, &self->vinfo,
&self->vinfo_drm)) {
GST_ELEMENT_ERROR (self, CORE, NEGOTIATION,
("Unsupported pixel format"),
("No support for %ux%u format %s", self->width, self->height,
@ -519,7 +534,7 @@ done:
self->output_state =
gst_v4l2_decoder_set_output_state (GST_VIDEO_DECODER (self), &self->vinfo,
self->width, self->height, vp9dec->input_state);
&self->vinfo_drm, self->width, self->height, vp9dec->input_state);
if (GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder)) {
if (self->streaming)
@ -552,6 +567,7 @@ gst_v4l2_codec_vp9_dec_decide_allocation (GstVideoDecoder * decoder,
GstQuery * query)
{
GstV4l2CodecVp9Dec *self = GST_V4L2_CODEC_VP9_DEC (decoder);
GstCaps *caps = NULL;
guint min = 0;
guint num_bitstream;
@ -560,11 +576,24 @@ gst_v4l2_codec_vp9_dec_decide_allocation (GstVideoDecoder * decoder,
if (self->streaming)
goto no_internal_changes;
g_clear_object (&self->src_pool);
g_clear_object (&self->src_allocator);
self->has_videometa = gst_query_find_allocation_meta (query,
GST_VIDEO_META_API_TYPE, NULL);
g_clear_object (&self->src_pool);
g_clear_object (&self->src_allocator);
gst_query_parse_allocation (query, &caps, NULL);
if (!caps) {
GST_ERROR_OBJECT (self, "No valid caps");
return FALSE;
}
if (gst_video_is_dma_drm_caps (caps) && !self->has_videometa) {
GST_ERROR_OBJECT (self,
"DMABuf caps negotiated without the mandatory support of VideoMeta");
return FALSE;
}
gst_caps_unref (caps);
if (gst_query_get_n_allocation_pools (query) > 0)
gst_query_parse_nth_allocation_pool (query, 0, NULL, NULL, &min, NULL);
@ -1111,6 +1140,7 @@ gst_v4l2_codec_vp9_dec_subinit (GstV4l2CodecVp9Dec * self,
{
self->decoder = gst_v4l2_decoder_new (klass->device);
gst_video_info_init (&self->vinfo);
gst_video_info_dma_drm_init (&self->vinfo_drm);
}
static void

View file

@ -410,6 +410,7 @@ gst_v4l2_decoder_probe_caps_for_format (GstV4l2Decoder * self,
gint index = 0;
GstCaps *caps, *tmp, *size_caps;
GstVideoFormat format;
guint32 drm_fourcc;
GST_DEBUG_OBJECT (self, "enumerate size for %" GST_FOURCC_FORMAT,
GST_FOURCC_ARGS (pixelformat));
@ -432,6 +433,31 @@ gst_v4l2_decoder_probe_caps_for_format (GstV4l2Decoder * self,
gst_caps_unref (tmp);
}
/* TODO: Add a V4L2 to DRM fourcc translator for formats that we don't support
* in software.
*/
drm_fourcc = gst_video_dma_drm_fourcc_from_format (format);
if (drm_fourcc /* != DRM_FORMAT_INVALID */ ) {
GstCaps *drm_caps;
drm_caps = gst_caps_new_simple ("video/x-raw", "format", G_TYPE_STRING,
"DMA_DRM", "drm-format", G_TYPE_STRING,
gst_video_dma_drm_fourcc_to_string (drm_fourcc, 0), NULL);
gst_caps_set_features_simple (drm_caps,
gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_DMABUF));
if (!gst_caps_is_empty (size_caps)) {
gst_caps_set_features_simple (size_caps,
gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_DMABUF));
tmp = drm_caps;
drm_caps =
gst_caps_intersect_full (tmp, size_caps, GST_CAPS_INTERSECT_FIRST);
gst_caps_unref (tmp);
}
caps = gst_caps_merge (drm_caps, caps);
}
gst_caps_unref (size_caps);
return caps;
@ -491,7 +517,7 @@ gst_v4l2_decoder_enum_src_formats (GstV4l2Decoder * self,
gboolean
gst_v4l2_decoder_select_src_format (GstV4l2Decoder * self, GstCaps * caps,
GstVideoInfo * vinfo)
GstVideoInfo * vinfo, GstVideoInfoDmaDrm * vinfo_drm)
{
gint ret;
struct v4l2_format fmt = {
@ -500,6 +526,7 @@ gst_v4l2_decoder_select_src_format (GstV4l2Decoder * self, GstCaps * caps,
GstVideoFormat format;
guint32 pix_fmt;
GstVideoInfo tmp_vinfo;
GstVideoInfoDmaDrm tmp_vinfo_drm;
if (gst_caps_is_empty (caps))
return FALSE;
@ -511,12 +538,15 @@ gst_v4l2_decoder_select_src_format (GstV4l2Decoder * self, GstCaps * caps,
}
gst_video_info_init (&tmp_vinfo);
gst_video_info_dma_drm_init (&tmp_vinfo_drm);
GST_DEBUG_OBJECT (self, "Original caps: %" GST_PTR_FORMAT, caps);
caps = gst_caps_fixate (caps);
GST_DEBUG_OBJECT (self, "Fixated caps: %" GST_PTR_FORMAT, caps);
if (gst_video_info_from_caps (&tmp_vinfo, caps)) {
if (gst_video_info_dma_drm_from_caps (&tmp_vinfo_drm, caps)) {
format = tmp_vinfo_drm.vinfo.finfo->format;
} else if (gst_video_info_from_caps (&tmp_vinfo, caps)) {
format = tmp_vinfo.finfo->format;
} else {
GST_WARNING_OBJECT (self, "Can't transform caps into video info!");
@ -547,6 +577,17 @@ gst_v4l2_decoder_select_src_format (GstV4l2Decoder * self, GstCaps * caps,
return FALSE;
}
if (tmp_vinfo_drm.drm_fourcc) {
if (!gst_video_info_dma_drm_from_video_info (vinfo_drm, vinfo, 0)) {
GST_ERROR_OBJECT (self,
"Unsupported V4L2 pixelformat for DRM %" GST_FOURCC_FORMAT,
GST_FOURCC_ARGS (fmt.fmt.pix_mp.pixelformat));
return FALSE;
}
} else {
gst_video_info_dma_drm_init (vinfo_drm);
}
GST_INFO_OBJECT (self, "Selected format %s %ix%i",
gst_video_format_to_string (vinfo->finfo->format),
vinfo->width, vinfo->height);
@ -556,15 +597,22 @@ gst_v4l2_decoder_select_src_format (GstV4l2Decoder * self, GstCaps * caps,
GstVideoCodecState *
gst_v4l2_decoder_set_output_state (GstVideoDecoder * decoder,
GstVideoInfo * vinfo, guint width, guint height,
GstVideoCodecState * reference)
GstVideoInfo * vinfo, GstVideoInfoDmaDrm * vinfo_drm, guint width,
guint height, GstVideoCodecState * reference)
{
GstVideoCodecState *state;
state = gst_video_decoder_set_output_state (decoder, vinfo->finfo->format,
width, height, reference);
state->caps = gst_video_info_to_caps (&state->info);
if (vinfo_drm->drm_fourcc /* != DRM_FORMAT_INVALID */ ) {
GstVideoInfoDmaDrm tmp_vinfo_drm;
gst_video_info_dma_drm_from_video_info (&tmp_vinfo_drm, &state->info, 0);
state->caps = gst_video_info_dma_drm_to_caps (&tmp_vinfo_drm);
} else {
state->caps = gst_video_info_to_caps (&state->info);
}
GST_DEBUG_OBJECT (decoder, "Setting caps: %" GST_PTR_FORMAT, state->caps);

View file

@ -72,10 +72,12 @@ GstCaps * gst_v4l2_decoder_enum_src_formats (GstV4l2Decoder * self,
gboolean gst_v4l2_decoder_select_src_format (GstV4l2Decoder * self,
GstCaps * caps,
GstVideoInfo * vinfo);
GstVideoInfo * vinfo,
GstVideoInfoDmaDrm * vinfo_drm);
GstVideoCodecState * gst_v4l2_decoder_set_output_state (GstVideoDecoder * decoder,
GstVideoInfo * vinfo,
GstVideoInfoDmaDrm * drm_info,
guint width,
guint height,
GstVideoCodecState * reference);