diff --git a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecav1dec.c b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecav1dec.c index 27940d1af3..eb85addad5 100644 --- a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecav1dec.c +++ b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecav1dec.c @@ -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)); } diff --git a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codech264dec.c b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codech264dec.c index de5dbdac71..39f63923c9 100644 --- a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codech264dec.c +++ b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codech264dec.c @@ -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); diff --git a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codech265dec.c b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codech265dec.c index c32ca9757f..7be7aa311c 100644 --- a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codech265dec.c +++ b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codech265dec.c @@ -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); diff --git a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecmpeg2dec.c b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecmpeg2dec.c index 749252a1ad..1f833eb662 100644 --- a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecmpeg2dec.c +++ b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecmpeg2dec.c @@ -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 diff --git a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecvp8dec.c b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecvp8dec.c index 6d6f49a8ae..02d88e9f1f 100644 --- a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecvp8dec.c +++ b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecvp8dec.c @@ -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 diff --git a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecvp9dec.c b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecvp9dec.c index 45ef5ac686..53be020b62 100644 --- a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecvp9dec.c +++ b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2codecvp9dec.c @@ -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 diff --git a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2decoder.c b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2decoder.c index a9c7e2caa4..251ce48ee7 100644 --- a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2decoder.c +++ b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2decoder.c @@ -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); diff --git a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2decoder.h b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2decoder.h index 457985f4ab..c726c94b46 100644 --- a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2decoder.h +++ b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2decoder.h @@ -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);