va: Apply the new DMA format:modifier pair negotiation in decoder

We will consider the DMA modifier for negotiation, setting caps and
memory pool allocation.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4044>
This commit is contained in:
He Junyan 2023-02-22 19:23:47 +08:00 committed by GStreamer Marge Bot
parent 919d398bff
commit 5df0bfa7cb
4 changed files with 113 additions and 32 deletions

View file

@ -265,7 +265,7 @@ _create_internal_pool (GstVaAV1Dec * self, gint width, gint height)
GstVideoFormat format; GstVideoFormat format;
gst_va_base_dec_get_preferred_format_and_caps_features (base, gst_va_base_dec_get_preferred_format_and_caps_features (base,
&format, NULL); &format, NULL, NULL);
if (format == GST_VIDEO_FORMAT_UNKNOWN) { if (format == GST_VIDEO_FORMAT_UNKNOWN) {
GST_WARNING_OBJECT (self, "Failed to get format for internal pool"); GST_WARNING_OBJECT (self, "Failed to get format for internal pool");
return NULL; return NULL;

View file

@ -501,7 +501,10 @@ gst_va_base_dec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query)
gst_query_parse_allocation (query, &caps, NULL); gst_query_parse_allocation (query, &caps, NULL);
if (!(caps && gst_video_info_from_caps (&info, caps))) if (!caps)
goto wrong_caps;
if (!gst_va_video_info_from_caps (&info, NULL, caps))
goto wrong_caps; goto wrong_caps;
has_videometa = gst_query_find_allocation_meta (query, has_videometa = gst_query_find_allocation_meta (query,
@ -515,9 +518,12 @@ gst_va_base_dec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query)
2. Some codec such as H265, it does not clean the DPB when new SPS 2. Some codec such as H265, it does not clean the DPB when new SPS
comes. The new SPS may set the crop window to top-left corner and comes. The new SPS may set the crop window to top-left corner and
so no video crop is needed here. But we may still have cached frames so no video crop is needed here. But we may still have cached frames
in DPB which need a copy. */ in DPB which need a copy.
if ((_need_video_crop (base) && !has_video_crop_meta) || 3. For DMA kind memory, because we may not be able to map this buffer,
base->apply_video_crop) { just disable the copy for crop. This may cause some alignment garbage. */
if (!gst_video_is_dma_drm_caps (caps) &&
((_need_video_crop (base) && !has_video_crop_meta) ||
base->apply_video_crop)) {
return _decide_allocation_for_video_crop (decoder, query, caps, &info); return _decide_allocation_for_video_crop (decoder, query, caps, &info);
} }
@ -758,16 +764,24 @@ gst_va_base_dec_class_init (GstVaBaseDecClass * klass, GstVaCodecs codec,
/* XXX: if chroma has not an available format, the first format is /* XXX: if chroma has not an available format, the first format is
* returned, relying on an hypothetical internal CSC */ * returned, relying on an hypothetical internal CSC */
static GstVideoFormat static GstVideoFormat
_find_video_format_from_chroma (const GValue * formats, guint chroma_type) _find_video_format_from_chroma (const GValue * formats, guint chroma_type,
gboolean drm_format, guint64 * modifier)
{ {
GstVideoFormat fmt; GstVideoFormat fmt;
guint32 fourcc;
guint i, num_values; guint i, num_values;
if (!formats) if (!formats)
return GST_VIDEO_FORMAT_UNKNOWN; return GST_VIDEO_FORMAT_UNKNOWN;
if (G_VALUE_HOLDS_STRING (formats)) { if (G_VALUE_HOLDS_STRING (formats)) {
return gst_video_format_from_string (g_value_get_string (formats)); if (drm_format) {
fourcc = gst_video_dma_drm_fourcc_from_string
(g_value_get_string (formats), modifier);
return gst_va_video_format_from_drm_fourcc (fourcc);
} else {
return gst_video_format_from_string (g_value_get_string (formats));
}
} else if (GST_VALUE_HOLDS_LIST (formats)) { } else if (GST_VALUE_HOLDS_LIST (formats)) {
GValue *val, *first_val = NULL; GValue *val, *first_val = NULL;
@ -778,13 +792,28 @@ _find_video_format_from_chroma (const GValue * formats, guint chroma_type)
continue; continue;
if (!first_val) if (!first_val)
first_val = val; first_val = val;
fmt = gst_video_format_from_string (g_value_get_string (val));
if (drm_format) {
fourcc = gst_video_dma_drm_fourcc_from_string (g_value_get_string (val),
modifier);
fmt = gst_va_video_format_from_drm_fourcc (fourcc);
} else {
fmt = gst_video_format_from_string (g_value_get_string (val));
}
if (gst_va_chroma_from_video_format (fmt) == chroma_type) if (gst_va_chroma_from_video_format (fmt) == chroma_type)
return fmt; return fmt;
} }
if (first_val) if (first_val) {
return gst_video_format_from_string (g_value_get_string (first_val)); if (drm_format) {
fourcc = gst_video_dma_drm_fourcc_from_string (g_value_get_string
(first_val), modifier);
return gst_va_video_format_from_drm_fourcc (fourcc);
} else {
return gst_video_format_from_string (g_value_get_string (first_val));
}
}
} }
return GST_VIDEO_FORMAT_UNKNOWN; return GST_VIDEO_FORMAT_UNKNOWN;
@ -792,13 +821,15 @@ _find_video_format_from_chroma (const GValue * formats, guint chroma_type)
static GstVideoFormat static GstVideoFormat
_caps_video_format_from_chroma (GstCaps * caps, GstCapsFeatures * features, _caps_video_format_from_chroma (GstCaps * caps, GstCapsFeatures * features,
guint chroma_type) guint chroma_type, guint64 * ret_modifier)
{ {
guint i, num_structures; guint i, num_structures;
gboolean drm_format;
GstCapsFeatures *feats; GstCapsFeatures *feats;
GstStructure *structure; GstStructure *structure;
const GValue *format; const GValue *format;
GstVideoFormat fmt, ret_fmt = GST_VIDEO_FORMAT_UNKNOWN; GstVideoFormat fmt, ret_fmt = GST_VIDEO_FORMAT_UNKNOWN;
guint64 modifier;
num_structures = gst_caps_get_size (caps); num_structures = gst_caps_get_size (caps);
for (i = 0; i < num_structures; i++) { for (i = 0; i < num_structures; i++) {
@ -806,19 +837,30 @@ _caps_video_format_from_chroma (GstCaps * caps, GstCapsFeatures * features,
if (!gst_caps_features_is_equal (feats, features)) if (!gst_caps_features_is_equal (feats, features))
continue; continue;
structure = gst_caps_get_structure (caps, i); structure = gst_caps_get_structure (caps, i);
format = gst_structure_get_value (structure, "format");
fmt = _find_video_format_from_chroma (format, chroma_type); if (gst_caps_features_contains (feats, GST_CAPS_FEATURE_MEMORY_DMABUF)) {
format = gst_structure_get_value (structure, "drm-format");
drm_format = TRUE;
} else {
format = gst_structure_get_value (structure, "format");
drm_format = FALSE;
}
fmt = _find_video_format_from_chroma (format, chroma_type, drm_format,
&modifier);
if (fmt == GST_VIDEO_FORMAT_UNKNOWN) if (fmt == GST_VIDEO_FORMAT_UNKNOWN)
continue; continue;
/* Record the first valid format as the fallback if we can if (ret_fmt == GST_VIDEO_FORMAT_UNKNOWN) {
not find a better one. */
if (ret_fmt == GST_VIDEO_FORMAT_UNKNOWN)
ret_fmt = fmt; ret_fmt = fmt;
if (ret_modifier)
*ret_modifier = modifier;
}
if (gst_va_chroma_from_video_format (fmt) == chroma_type) { if (gst_va_chroma_from_video_format (fmt) == chroma_type) {
ret_fmt = fmt; ret_fmt = fmt;
if (ret_modifier)
*ret_modifier = modifier;
break; break;
} }
} }
@ -828,13 +870,28 @@ _caps_video_format_from_chroma (GstCaps * caps, GstCapsFeatures * features,
static GstVideoFormat static GstVideoFormat
_default_video_format_from_chroma (GstVaBaseDec * base, _default_video_format_from_chroma (GstVaBaseDec * base,
GstCapsFeatures * features, guint chroma_type) GstCaps * preferred_caps, GstCapsFeatures * features, guint chroma_type,
guint64 * modifier)
{ {
GstCaps *tmpl_caps; GstCaps *tmpl_caps;
GstVideoFormat ret = GST_VIDEO_FORMAT_UNKNOWN; GstVideoFormat ret = GST_VIDEO_FORMAT_UNKNOWN;
tmpl_caps = gst_pad_get_pad_template_caps (GST_VIDEO_DECODER_SRC_PAD (base)); tmpl_caps = gst_pad_get_pad_template_caps (GST_VIDEO_DECODER_SRC_PAD (base));
ret = _caps_video_format_from_chroma (tmpl_caps, features, chroma_type);
/* Make the preferred caps in the order of our template */
if (preferred_caps) {
GstCaps *tmp;
g_assert (!gst_caps_is_empty (preferred_caps));
tmp = tmpl_caps;
tmpl_caps = gst_caps_intersect_full (tmp, preferred_caps,
GST_CAPS_INTERSECT_FIRST);
gst_caps_unref (tmp);
}
ret = _caps_video_format_from_chroma (tmpl_caps, features, chroma_type,
modifier);
gst_caps_unref (tmpl_caps); gst_caps_unref (tmpl_caps);
return ret; return ret;
@ -858,9 +915,10 @@ _downstream_has_video_meta (GstVaBaseDec * base, GstCaps * caps)
void void
gst_va_base_dec_get_preferred_format_and_caps_features (GstVaBaseDec * base, gst_va_base_dec_get_preferred_format_and_caps_features (GstVaBaseDec * base,
GstVideoFormat * format, GstCapsFeatures ** capsfeatures) GstVideoFormat * format, GstCapsFeatures ** capsfeatures,
guint64 * modifier)
{ {
GstCaps *peer_caps, *preferred_caps = NULL; GstCaps *peer_caps = NULL, *preferred_caps = NULL;
GstCapsFeatures *features; GstCapsFeatures *features;
GstStructure *structure; GstStructure *structure;
guint num_structures, i; guint num_structures, i;
@ -897,16 +955,14 @@ gst_va_base_dec_get_preferred_format_and_caps_features (GstVaBaseDec * base,
} }
if (!preferred_caps) if (!preferred_caps)
preferred_caps = peer_caps; preferred_caps = gst_caps_copy (peer_caps);
else
gst_clear_caps (&peer_caps);
if (gst_caps_is_empty (preferred_caps)) { if (gst_caps_is_empty (preferred_caps)) {
if (capsfeatures) if (capsfeatures)
*capsfeatures = NULL; /* system memory */ *capsfeatures = NULL; /* system memory */
if (format) { if (format) {
*format = _default_video_format_from_chroma (base, *format = _default_video_format_from_chroma (base, NULL,
GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY, base->rt_format); GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY, base->rt_format, NULL);
} }
goto bail; goto bail;
} }
@ -922,7 +978,10 @@ gst_va_base_dec_get_preferred_format_and_caps_features (GstVaBaseDec * base,
&& !_downstream_has_video_meta (base, preferred_caps)) { && !_downstream_has_video_meta (base, preferred_caps)) {
GST_INFO_OBJECT (base, "Downstream reports ANY caps but without" GST_INFO_OBJECT (base, "Downstream reports ANY caps but without"
" VideoMeta support; fallback to system memory."); " VideoMeta support; fallback to system memory.");
features = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY; features = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
gst_clear_caps (&preferred_caps);
preferred_caps = gst_caps_copy (peer_caps);
} }
@ -932,12 +991,13 @@ gst_va_base_dec_get_preferred_format_and_caps_features (GstVaBaseDec * base,
/* Use the format from chroma and available format for selected /* Use the format from chroma and available format for selected
* capsfeature */ * capsfeature */
if (format) { if (format) {
*format = _default_video_format_from_chroma (base, features, *format = _default_video_format_from_chroma (base, preferred_caps,
base->rt_format); features, base->rt_format, modifier);
} }
bail: bail:
gst_clear_caps (&preferred_caps); gst_clear_caps (&preferred_caps);
gst_clear_caps (&peer_caps);
} }
static gboolean static gboolean
@ -1143,6 +1203,7 @@ gst_va_base_dec_set_output_state (GstVaBaseDec * base)
{ {
GstVideoDecoder *decoder = GST_VIDEO_DECODER (base); GstVideoDecoder *decoder = GST_VIDEO_DECODER (base);
GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN; GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
guint64 modifier;
GstCapsFeatures *capsfeatures = NULL; GstCapsFeatures *capsfeatures = NULL;
GstVideoInfo *info = &base->output_info; GstVideoInfo *info = &base->output_info;
@ -1150,7 +1211,7 @@ gst_va_base_dec_set_output_state (GstVaBaseDec * base)
gst_video_codec_state_unref (base->output_state); gst_video_codec_state_unref (base->output_state);
gst_va_base_dec_get_preferred_format_and_caps_features (base, &format, gst_va_base_dec_get_preferred_format_and_caps_features (base, &format,
&capsfeatures); &capsfeatures, &modifier);
if (format == GST_VIDEO_FORMAT_UNKNOWN) if (format == GST_VIDEO_FORMAT_UNKNOWN)
return FALSE; return FALSE;
@ -1160,7 +1221,15 @@ gst_va_base_dec_set_output_state (GstVaBaseDec * base)
GST_VIDEO_INFO_HEIGHT (info), base->input_state); GST_VIDEO_INFO_HEIGHT (info), base->input_state);
/* set caps feature */ /* set caps feature */
base->output_state->caps = gst_video_info_to_caps (&base->output_state->info); if (capsfeatures && gst_caps_features_contains (capsfeatures,
GST_CAPS_FEATURE_MEMORY_DMABUF)) {
base->output_state->caps =
gst_va_video_info_to_dma_caps (&base->output_state->info, modifier);
} else {
base->output_state->caps =
gst_video_info_to_caps (&base->output_state->info);
}
if (capsfeatures) if (capsfeatures)
gst_caps_set_features_simple (base->output_state->caps, capsfeatures); gst_caps_set_features_simple (base->output_state->caps, capsfeatures);

View file

@ -133,7 +133,8 @@ void gst_va_base_dec_class_init (GstVaBaseDecClass * k
gboolean gst_va_base_dec_close (GstVideoDecoder * decoder); gboolean gst_va_base_dec_close (GstVideoDecoder * decoder);
void gst_va_base_dec_get_preferred_format_and_caps_features (GstVaBaseDec * base, void gst_va_base_dec_get_preferred_format_and_caps_features (GstVaBaseDec * base,
GstVideoFormat * format, GstVideoFormat * format,
GstCapsFeatures ** capsfeatures); GstCapsFeatures ** capsfeatures,
guint64 * modifier);
gboolean gst_va_base_dec_copy_output_buffer (GstVaBaseDec * base, gboolean gst_va_base_dec_copy_output_buffer (GstVaBaseDec * base,
GstVideoCodecFrame * codec_frame); GstVideoCodecFrame * codec_frame);
gboolean gst_va_base_dec_process_output (GstVaBaseDec * base, gboolean gst_va_base_dec_process_output (GstVaBaseDec * base,

View file

@ -46,6 +46,7 @@
#include <gst/va/gstvavideoformat.h> #include <gst/va/gstvavideoformat.h>
#include "gstvacaps.h"
#include "gstvabasedec.h" #include "gstvabasedec.h"
GST_DEBUG_CATEGORY_STATIC (gst_va_jpegdec_debug); GST_DEBUG_CATEGORY_STATIC (gst_va_jpegdec_debug);
@ -356,6 +357,7 @@ gst_va_jpeg_dec_negotiate (GstVideoDecoder * decoder)
GstVaBaseDec *base = GST_VA_BASE_DEC (decoder); GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
GstVaJpegDec *self = GST_VA_JPEG_DEC (decoder); GstVaJpegDec *self = GST_VA_JPEG_DEC (decoder);
GstVideoFormat format; GstVideoFormat format;
guint64 modifier;
GstCapsFeatures *capsfeatures = NULL; GstCapsFeatures *capsfeatures = NULL;
/* Ignore downstream renegotiation request. */ /* Ignore downstream renegotiation request. */
@ -386,7 +388,7 @@ gst_va_jpeg_dec_negotiate (GstVideoDecoder * decoder)
base->rt_format = VA_RT_FORMAT_RGBP; base->rt_format = VA_RT_FORMAT_RGBP;
gst_va_base_dec_get_preferred_format_and_caps_features (base, &format, gst_va_base_dec_get_preferred_format_and_caps_features (base, &format,
&capsfeatures); &capsfeatures, &modifier);
if (format == GST_VIDEO_FORMAT_UNKNOWN) if (format == GST_VIDEO_FORMAT_UNKNOWN)
return FALSE; return FALSE;
@ -402,7 +404,16 @@ gst_va_jpeg_dec_negotiate (GstVideoDecoder * decoder)
gst_video_decoder_set_output_state (decoder, format, gst_video_decoder_set_output_state (decoder, format,
base->width, base->height, base->input_state); base->width, base->height, base->input_state);
base->output_state->caps = gst_video_info_to_caps (&base->output_state->info); /* set caps feature */
if (capsfeatures && gst_caps_features_contains (capsfeatures,
GST_CAPS_FEATURE_MEMORY_DMABUF)) {
base->output_state->caps =
gst_va_video_info_to_dma_caps (&base->output_state->info, modifier);
} else {
base->output_state->caps =
gst_video_info_to_caps (&base->output_state->info);
}
if (capsfeatures) if (capsfeatures)
gst_caps_set_features_simple (base->output_state->caps, capsfeatures); gst_caps_set_features_simple (base->output_state->caps, capsfeatures);