mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-07-18 04:18:20 +00:00
mpeg2: fix decoding of high profile streams.
Allow MPEG-2 High profile streams only if the HW supports that profile or no High profile specific bits are used, and thus Main profile could be used instead. i.e. chroma_format is 4:2:0, intra_dc_precision is not set to 11 and no sequence_scalable_extension() was parsed.
This commit is contained in:
parent
84b5fc5e58
commit
9c8b85b3c7
1
NEWS
1
NEWS
|
@ -5,6 +5,7 @@ Copyright (C) 2011 Collabora
|
||||||
|
|
||||||
Version 0.3.7 - DD.Apr.2012
|
Version 0.3.7 - DD.Apr.2012
|
||||||
* Fix vaapidecode to report unsupported codec profiles
|
* Fix vaapidecode to report unsupported codec profiles
|
||||||
|
* Fix decoding of MPEG-2 High profile streams compatible with Main profile
|
||||||
* Don't forcibly resize user provided X windows (Holger Kaelberer)
|
* Don't forcibly resize user provided X windows (Holger Kaelberer)
|
||||||
* Recalculate render rect only if caps are negotiated (Holger Kaelberer)
|
* Recalculate render rect only if caps are negotiated (Holger Kaelberer)
|
||||||
|
|
||||||
|
|
|
@ -165,6 +165,7 @@ pts_eval(PTSGenerator *tsg, GstClockTime pic_pts, guint pic_tsn)
|
||||||
|
|
||||||
struct _GstVaapiDecoderMpeg2Private {
|
struct _GstVaapiDecoderMpeg2Private {
|
||||||
GstVaapiProfile profile;
|
GstVaapiProfile profile;
|
||||||
|
GstVaapiProfile hw_profile;
|
||||||
guint width;
|
guint width;
|
||||||
guint height;
|
guint height;
|
||||||
guint fps_n;
|
guint fps_n;
|
||||||
|
@ -329,13 +330,66 @@ copy_quant_matrix(guint8 dst[64], const guint8 src[64])
|
||||||
memcpy(dst, src, 64);
|
memcpy(dst, src, 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
get_profile_str(GstVaapiProfile profile)
|
||||||
|
{
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
switch (profile) {
|
||||||
|
case GST_VAAPI_PROFILE_MPEG2_SIMPLE: str = "simple"; break;
|
||||||
|
case GST_VAAPI_PROFILE_MPEG2_MAIN: str = "main"; break;
|
||||||
|
case GST_VAAPI_PROFILE_MPEG2_HIGH: str = "high"; break;
|
||||||
|
default: str = "<unknown>"; break;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstVaapiProfile
|
||||||
|
get_profile(GstVaapiDecoderMpeg2 *decoder, GstVaapiEntrypoint entrypoint)
|
||||||
|
{
|
||||||
|
GstVaapiDisplay * const va_display = GST_VAAPI_DECODER_DISPLAY(decoder);
|
||||||
|
GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
|
||||||
|
GstVaapiProfile profile = priv->profile;
|
||||||
|
|
||||||
|
do {
|
||||||
|
/* Return immediately if the exact same profile was found */
|
||||||
|
if (gst_vaapi_display_has_decoder(va_display, profile, entrypoint))
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Otherwise, try to map to a higher profile */
|
||||||
|
switch (profile) {
|
||||||
|
case GST_VAAPI_PROFILE_MPEG2_SIMPLE:
|
||||||
|
profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
|
||||||
|
break;
|
||||||
|
case GST_VAAPI_PROFILE_MPEG2_MAIN:
|
||||||
|
profile = GST_VAAPI_PROFILE_MPEG2_HIGH;
|
||||||
|
break;
|
||||||
|
case GST_VAAPI_PROFILE_MPEG2_HIGH:
|
||||||
|
// Try to map to main profile if no high profile specific bits used
|
||||||
|
if (priv->profile == profile &&
|
||||||
|
!priv->has_seq_scalable_ext &&
|
||||||
|
(priv->has_seq_ext && priv->seq_ext.chroma_format == 1)) {
|
||||||
|
profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// fall-through
|
||||||
|
default:
|
||||||
|
profile = GST_VAAPI_PROFILE_UNKNOWN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (profile != GST_VAAPI_PROFILE_UNKNOWN);
|
||||||
|
|
||||||
|
if (profile != priv->profile)
|
||||||
|
GST_INFO("forced %s profile to %s profile",
|
||||||
|
get_profile_str(priv->profile), get_profile_str(profile));
|
||||||
|
return profile;
|
||||||
|
}
|
||||||
|
|
||||||
static GstVaapiDecoderStatus
|
static GstVaapiDecoderStatus
|
||||||
ensure_context(GstVaapiDecoderMpeg2 *decoder)
|
ensure_context(GstVaapiDecoderMpeg2 *decoder)
|
||||||
{
|
{
|
||||||
GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
|
GstVaapiDecoderMpeg2Private * const priv = decoder->priv;
|
||||||
GstVaapiProfile profiles[2];
|
|
||||||
GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
|
GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
|
||||||
guint i, n_profiles = 0;
|
|
||||||
gboolean reset_context = FALSE;
|
gboolean reset_context = FALSE;
|
||||||
|
|
||||||
if (priv->profile_changed) {
|
if (priv->profile_changed) {
|
||||||
|
@ -343,18 +397,9 @@ ensure_context(GstVaapiDecoderMpeg2 *decoder)
|
||||||
priv->profile_changed = FALSE;
|
priv->profile_changed = FALSE;
|
||||||
reset_context = TRUE;
|
reset_context = TRUE;
|
||||||
|
|
||||||
profiles[n_profiles++] = priv->profile;
|
priv->hw_profile = get_profile(decoder, entrypoint);
|
||||||
if (priv->profile == GST_VAAPI_PROFILE_MPEG2_SIMPLE)
|
if (priv->hw_profile == GST_VAAPI_PROFILE_UNKNOWN)
|
||||||
profiles[n_profiles++] = GST_VAAPI_PROFILE_MPEG2_MAIN;
|
|
||||||
|
|
||||||
for (i = 0; i < n_profiles; i++) {
|
|
||||||
if (gst_vaapi_display_has_decoder(GST_VAAPI_DECODER_DISPLAY(decoder),
|
|
||||||
profiles[i], entrypoint))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i == n_profiles)
|
|
||||||
return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
|
return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
|
||||||
priv->profile = profiles[i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->size_changed) {
|
if (priv->size_changed) {
|
||||||
|
@ -366,7 +411,7 @@ ensure_context(GstVaapiDecoderMpeg2 *decoder)
|
||||||
if (reset_context) {
|
if (reset_context) {
|
||||||
reset_context = gst_vaapi_decoder_ensure_context(
|
reset_context = gst_vaapi_decoder_ensure_context(
|
||||||
GST_VAAPI_DECODER(decoder),
|
GST_VAAPI_DECODER(decoder),
|
||||||
priv->profile,
|
priv->hw_profile,
|
||||||
entrypoint,
|
entrypoint,
|
||||||
priv->width, priv->height
|
priv->width, priv->height
|
||||||
);
|
);
|
||||||
|
@ -522,6 +567,9 @@ decode_sequence_ext(GstVaapiDecoderMpeg2 *decoder, guchar *buf, guint buf_size)
|
||||||
case GST_MPEG_VIDEO_PROFILE_MAIN:
|
case GST_MPEG_VIDEO_PROFILE_MAIN:
|
||||||
profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
|
profile = GST_VAAPI_PROFILE_MPEG2_MAIN;
|
||||||
break;
|
break;
|
||||||
|
case GST_MPEG_VIDEO_PROFILE_HIGH:
|
||||||
|
profile = GST_VAAPI_PROFILE_MPEG2_HIGH;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
GST_ERROR("unsupported profile %d", seq_ext->profile);
|
GST_ERROR("unsupported profile %d", seq_ext->profile);
|
||||||
return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
|
return GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
|
||||||
|
@ -1080,6 +1128,7 @@ gst_vaapi_decoder_mpeg2_init(GstVaapiDecoderMpeg2 *decoder)
|
||||||
priv->height = 0;
|
priv->height = 0;
|
||||||
priv->fps_n = 0;
|
priv->fps_n = 0;
|
||||||
priv->fps_d = 0;
|
priv->fps_d = 0;
|
||||||
|
priv->hw_profile = GST_VAAPI_PROFILE_UNKNOWN;
|
||||||
priv->profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
|
priv->profile = GST_VAAPI_PROFILE_MPEG2_SIMPLE;
|
||||||
priv->current_picture = NULL;
|
priv->current_picture = NULL;
|
||||||
priv->adapter = NULL;
|
priv->adapter = NULL;
|
||||||
|
|
|
@ -65,12 +65,16 @@ enum _GstVaapiCodec {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstVaapiProfile:
|
* GstVaapiProfile:
|
||||||
|
* @GST_VAAPI_PROFILE_UNKNOWN:
|
||||||
|
* Unknown profile, used for initializers
|
||||||
* @GST_VAAPI_PROFILE_MPEG1:
|
* @GST_VAAPI_PROFILE_MPEG1:
|
||||||
* MPEG-1
|
* MPEG-1
|
||||||
* @GST_VAAPI_PROFILE_MPEG2_SIMPLE:
|
* @GST_VAAPI_PROFILE_MPEG2_SIMPLE:
|
||||||
* MPEG-2 simple profile
|
* MPEG-2 simple profile
|
||||||
* @GST_VAAPI_PROFILE_MPEG2_MAIN:
|
* @GST_VAAPI_PROFILE_MPEG2_MAIN:
|
||||||
* MPEG-2 main profile
|
* MPEG-2 main profile
|
||||||
|
* @GST_VAAPI_PROFILE_MPEG2_HIGH:
|
||||||
|
* MPEG-2 high profile
|
||||||
* @GST_VAAPI_PROFILE_MPEG4_SIMPLE:
|
* @GST_VAAPI_PROFILE_MPEG4_SIMPLE:
|
||||||
* MPEG-4 Part-2 simple profile
|
* MPEG-4 Part-2 simple profile
|
||||||
* @GST_VAAPI_PROFILE_MPEG4_ADVANCED_SIMPLE:
|
* @GST_VAAPI_PROFILE_MPEG4_ADVANCED_SIMPLE:
|
||||||
|
@ -95,9 +99,11 @@ enum _GstVaapiCodec {
|
||||||
* The set of all profiles for #GstVaapiProfile.
|
* The set of all profiles for #GstVaapiProfile.
|
||||||
*/
|
*/
|
||||||
enum _GstVaapiProfile {
|
enum _GstVaapiProfile {
|
||||||
|
GST_VAAPI_PROFILE_UNKNOWN = 0,
|
||||||
GST_VAAPI_PROFILE_MPEG1 = GST_VAAPI_MAKE_PROFILE(MPEG1,1),
|
GST_VAAPI_PROFILE_MPEG1 = GST_VAAPI_MAKE_PROFILE(MPEG1,1),
|
||||||
GST_VAAPI_PROFILE_MPEG2_SIMPLE = GST_VAAPI_MAKE_PROFILE(MPEG2,1),
|
GST_VAAPI_PROFILE_MPEG2_SIMPLE = GST_VAAPI_MAKE_PROFILE(MPEG2,1),
|
||||||
GST_VAAPI_PROFILE_MPEG2_MAIN = GST_VAAPI_MAKE_PROFILE(MPEG2,2),
|
GST_VAAPI_PROFILE_MPEG2_MAIN = GST_VAAPI_MAKE_PROFILE(MPEG2,2),
|
||||||
|
GST_VAAPI_PROFILE_MPEG2_HIGH = GST_VAAPI_MAKE_PROFILE(MPEG2,3),
|
||||||
GST_VAAPI_PROFILE_MPEG4_SIMPLE = GST_VAAPI_MAKE_PROFILE(MPEG4,1),
|
GST_VAAPI_PROFILE_MPEG4_SIMPLE = GST_VAAPI_MAKE_PROFILE(MPEG4,1),
|
||||||
GST_VAAPI_PROFILE_MPEG4_ADVANCED_SIMPLE = GST_VAAPI_MAKE_PROFILE(MPEG4,2),
|
GST_VAAPI_PROFILE_MPEG4_ADVANCED_SIMPLE = GST_VAAPI_MAKE_PROFILE(MPEG4,2),
|
||||||
GST_VAAPI_PROFILE_MPEG4_MAIN = GST_VAAPI_MAKE_PROFILE(MPEG4,3),
|
GST_VAAPI_PROFILE_MPEG4_MAIN = GST_VAAPI_MAKE_PROFILE(MPEG4,3),
|
||||||
|
|
Loading…
Reference in a new issue