mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-03 14:08:56 +00:00
avviddec: Expose std-compliance option
Default compliance mode (i.e., FF_COMPLIANCE_NORMAL) might not strictly follow specification. This property will allow user to specifiy expected compliance mode. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3311>
This commit is contained in:
parent
2cdfa8f419
commit
af05abdb79
4 changed files with 96 additions and 12 deletions
|
@ -493,3 +493,38 @@ gst_ffmpeg_auto_max_threads (void)
|
||||||
|
|
||||||
return (int) (n_threads);
|
return (int) (n_threads);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GType
|
||||||
|
gst_av_codec_compliance_get_type (void)
|
||||||
|
{
|
||||||
|
static gsize compliance_type = 0;
|
||||||
|
|
||||||
|
if (g_once_init_enter (&compliance_type)) {
|
||||||
|
static const GEnumValue types[] = {
|
||||||
|
{GST_AV_CODEC_COMPLIANCE_AUTO,
|
||||||
|
"The decoder automatically decides. If the pipeline is live, it will"
|
||||||
|
"use `normal` mode, and `strict` otherwise.", "auto"},
|
||||||
|
{GST_AV_CODEC_COMPLIANCE_VERY_STRICT,
|
||||||
|
"VeryStrict: Strictly conform to an older more strict version "
|
||||||
|
"of the spec or reference software", "very-strict"},
|
||||||
|
{GST_AV_CODEC_COMPLIANCE_STRICT,
|
||||||
|
"Strict: Strictly conform to all the things in the spec no matter "
|
||||||
|
"what consequences", "strict"},
|
||||||
|
{GST_AV_CODEC_COMPLIANCE_NORMAL, "Normal", "normal"},
|
||||||
|
{GST_AV_CODEC_COMPLIANCE_UNOFFICIAL,
|
||||||
|
"Unofficial: Allow unofficial extensions "
|
||||||
|
"(decoder will not differentiate this with \"normal\")",
|
||||||
|
"unofficial"},
|
||||||
|
{GST_AV_CODEC_COMPLIANCE_EXPERIMENTAL,
|
||||||
|
"Experimental: Allow nonstandardized experimental things "
|
||||||
|
"(decoder will not differentiate this with \"normal\")",
|
||||||
|
"experimental"},
|
||||||
|
{0, NULL, NULL},
|
||||||
|
};
|
||||||
|
GType tmp = g_enum_register_static ("GstAvCodecCompliance", types);
|
||||||
|
g_once_init_leave (&compliance_type, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (GType) compliance_type;
|
||||||
|
}
|
||||||
|
|
|
@ -114,4 +114,18 @@ av_smp_format_depth(enum AVSampleFormat smp_fmt);
|
||||||
GstBuffer *
|
GstBuffer *
|
||||||
new_aligned_buffer (gint size);
|
new_aligned_buffer (gint size);
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GST_AV_CODEC_COMPLIANCE_AUTO = G_MAXINT,
|
||||||
|
GST_AV_CODEC_COMPLIANCE_VERY_STRICT = FF_COMPLIANCE_VERY_STRICT,
|
||||||
|
GST_AV_CODEC_COMPLIANCE_STRICT = FF_COMPLIANCE_STRICT,
|
||||||
|
GST_AV_CODEC_COMPLIANCE_NORMAL = FF_COMPLIANCE_NORMAL,
|
||||||
|
GST_AV_CODEC_COMPLIANCE_UNOFFICIAL = FF_COMPLIANCE_UNOFFICIAL,
|
||||||
|
GST_AV_CODEC_COMPLIANCE_EXPERIMENTAL = FF_COMPLIANCE_EXPERIMENTAL,
|
||||||
|
} GstAvCodecCompliance;
|
||||||
|
|
||||||
|
#define GST_TYPE_AV_CODEC_COMPLIANCE (gst_av_codec_compliance_get_type())
|
||||||
|
GType gst_av_codec_compliance_get_type (void);
|
||||||
|
|
||||||
|
|
||||||
#endif /* __GST_FFMPEG_UTILS_H__ */
|
#endif /* __GST_FFMPEG_UTILS_H__ */
|
||||||
|
|
|
@ -48,6 +48,7 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
|
||||||
#define DEFAULT_STRIDE_ALIGN 31
|
#define DEFAULT_STRIDE_ALIGN 31
|
||||||
#define DEFAULT_ALLOC_PARAM { 0, DEFAULT_STRIDE_ALIGN, 0, 0, }
|
#define DEFAULT_ALLOC_PARAM { 0, DEFAULT_STRIDE_ALIGN, 0, 0, }
|
||||||
#define DEFAULT_THREAD_TYPE 0
|
#define DEFAULT_THREAD_TYPE 0
|
||||||
|
#define DEFAULT_STD_COMPLIANCE GST_AV_CODEC_COMPLIANCE_AUTO
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -59,6 +60,7 @@ enum
|
||||||
PROP_MAX_THREADS,
|
PROP_MAX_THREADS,
|
||||||
PROP_OUTPUT_CORRUPT,
|
PROP_OUTPUT_CORRUPT,
|
||||||
PROP_THREAD_TYPE,
|
PROP_THREAD_TYPE,
|
||||||
|
PROP_STD_COMPLIANCE,
|
||||||
PROP_LAST
|
PROP_LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -293,6 +295,18 @@ gst_ffmpegviddec_class_init (GstFFMpegVidDecClass * klass)
|
||||||
DEFAULT_THREAD_TYPE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
DEFAULT_THREAD_TYPE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstFFMpegVidDec::std-compliance:
|
||||||
|
*
|
||||||
|
* Specifies standard compliance mode to use
|
||||||
|
*
|
||||||
|
* Since: 1.20
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_STD_COMPLIANCE,
|
||||||
|
g_param_spec_enum ("std-compliance", "Standard Compliance",
|
||||||
|
"Standard compliance mode to use", GST_TYPE_AV_CODEC_COMPLIANCE,
|
||||||
|
DEFAULT_STD_COMPLIANCE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
viddec_class->set_format = gst_ffmpegviddec_set_format;
|
viddec_class->set_format = gst_ffmpegviddec_set_format;
|
||||||
viddec_class->handle_frame = gst_ffmpegviddec_handle_frame;
|
viddec_class->handle_frame = gst_ffmpegviddec_handle_frame;
|
||||||
viddec_class->start = gst_ffmpegviddec_start;
|
viddec_class->start = gst_ffmpegviddec_start;
|
||||||
|
@ -308,6 +322,7 @@ gst_ffmpegviddec_class_init (GstFFMpegVidDecClass * klass)
|
||||||
gst_type_mark_as_plugin_api (GST_FFMPEGVIDDEC_TYPE_LOWRES, 0);
|
gst_type_mark_as_plugin_api (GST_FFMPEGVIDDEC_TYPE_LOWRES, 0);
|
||||||
gst_type_mark_as_plugin_api (GST_FFMPEGVIDDEC_TYPE_SKIPFRAME, 0);
|
gst_type_mark_as_plugin_api (GST_FFMPEGVIDDEC_TYPE_SKIPFRAME, 0);
|
||||||
gst_type_mark_as_plugin_api (GST_FFMPEGVIDDEC_TYPE_THREAD_TYPE, 0);
|
gst_type_mark_as_plugin_api (GST_FFMPEGVIDDEC_TYPE_THREAD_TYPE, 0);
|
||||||
|
gst_type_mark_as_plugin_api (GST_TYPE_AV_CODEC_COMPLIANCE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -492,6 +507,8 @@ gst_ffmpegviddec_set_format (GstVideoDecoder * decoder,
|
||||||
GstFFMpegVidDecClass *oclass;
|
GstFFMpegVidDecClass *oclass;
|
||||||
GstClockTime latency = GST_CLOCK_TIME_NONE;
|
GstClockTime latency = GST_CLOCK_TIME_NONE;
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
|
gboolean is_live;
|
||||||
|
GstQuery *query;
|
||||||
|
|
||||||
ffmpegdec = (GstFFMpegVidDec *) decoder;
|
ffmpegdec = (GstFFMpegVidDec *) decoder;
|
||||||
oclass = (GstFFMpegVidDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));
|
oclass = (GstFFMpegVidDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));
|
||||||
|
@ -568,23 +585,21 @@ gst_ffmpegviddec_set_format (GstVideoDecoder * decoder,
|
||||||
ffmpegdec->context->lowres = ffmpegdec->lowres;
|
ffmpegdec->context->lowres = ffmpegdec->lowres;
|
||||||
ffmpegdec->context->skip_frame = ffmpegdec->skip_frame;
|
ffmpegdec->context->skip_frame = ffmpegdec->skip_frame;
|
||||||
|
|
||||||
|
|
||||||
|
query = gst_query_new_latency ();
|
||||||
|
is_live = FALSE;
|
||||||
|
/* Check if upstream is live. If it isn't we can enable frame based
|
||||||
|
* threading, which is adding latency */
|
||||||
|
if (gst_pad_peer_query (GST_VIDEO_DECODER_SINK_PAD (ffmpegdec), query)) {
|
||||||
|
gst_query_parse_latency (query, &is_live, NULL, NULL);
|
||||||
|
}
|
||||||
|
gst_query_unref (query);
|
||||||
|
|
||||||
if (ffmpegdec->thread_type) {
|
if (ffmpegdec->thread_type) {
|
||||||
GST_DEBUG_OBJECT (ffmpegdec, "Use requested thread type 0x%x",
|
GST_DEBUG_OBJECT (ffmpegdec, "Use requested thread type 0x%x",
|
||||||
ffmpegdec->thread_type);
|
ffmpegdec->thread_type);
|
||||||
ffmpegdec->context->thread_type = ffmpegdec->thread_type;
|
ffmpegdec->context->thread_type = ffmpegdec->thread_type;
|
||||||
} else {
|
} else {
|
||||||
GstQuery *query;
|
|
||||||
gboolean is_live;
|
|
||||||
|
|
||||||
query = gst_query_new_latency ();
|
|
||||||
is_live = FALSE;
|
|
||||||
/* Check if upstream is live. If it isn't we can enable frame based
|
|
||||||
* threading, which is adding latency */
|
|
||||||
if (gst_pad_peer_query (GST_VIDEO_DECODER_SINK_PAD (ffmpegdec), query)) {
|
|
||||||
gst_query_parse_latency (query, &is_live, NULL, NULL);
|
|
||||||
}
|
|
||||||
gst_query_unref (query);
|
|
||||||
|
|
||||||
if (is_live)
|
if (is_live)
|
||||||
ffmpegdec->context->thread_type = FF_THREAD_SLICE;
|
ffmpegdec->context->thread_type = FF_THREAD_SLICE;
|
||||||
else
|
else
|
||||||
|
@ -603,6 +618,19 @@ gst_ffmpegviddec_set_format (GstVideoDecoder * decoder,
|
||||||
} else
|
} else
|
||||||
ffmpegdec->context->thread_count = ffmpegdec->max_threads;
|
ffmpegdec->context->thread_count = ffmpegdec->max_threads;
|
||||||
|
|
||||||
|
if (ffmpegdec->std_compliance == GST_AV_CODEC_COMPLIANCE_AUTO) {
|
||||||
|
/* Normal yields lower latency, but fails some compliance check */
|
||||||
|
if (is_live || ffmpegdec->context->thread_type == FF_THREAD_SLICE) {
|
||||||
|
ffmpegdec->context->strict_std_compliance =
|
||||||
|
GST_AV_CODEC_COMPLIANCE_NORMAL;
|
||||||
|
} else {
|
||||||
|
ffmpegdec->context->strict_std_compliance =
|
||||||
|
GST_AV_CODEC_COMPLIANCE_STRICT;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ffmpegdec->context->strict_std_compliance = ffmpegdec->std_compliance;
|
||||||
|
}
|
||||||
|
|
||||||
if (oclass->in_plugin->id == AV_CODEC_ID_H264) {
|
if (oclass->in_plugin->id == AV_CODEC_ID_H264) {
|
||||||
GstStructure *s = gst_caps_get_structure (state->caps, 0);
|
GstStructure *s = gst_caps_get_structure (state->caps, 0);
|
||||||
const char *alignment;
|
const char *alignment;
|
||||||
|
@ -2417,6 +2445,9 @@ gst_ffmpegviddec_set_property (GObject * object,
|
||||||
case PROP_THREAD_TYPE:
|
case PROP_THREAD_TYPE:
|
||||||
ffmpegdec->thread_type = g_value_get_flags (value);
|
ffmpegdec->thread_type = g_value_get_flags (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_STD_COMPLIANCE:
|
||||||
|
ffmpegdec->std_compliance = g_value_get_enum (value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -2453,6 +2484,9 @@ gst_ffmpegviddec_get_property (GObject * object,
|
||||||
case PROP_THREAD_TYPE:
|
case PROP_THREAD_TYPE:
|
||||||
g_value_set_flags (value, ffmpegdec->thread_type);
|
g_value_set_flags (value, ffmpegdec->thread_type);
|
||||||
break;
|
break;
|
||||||
|
case PROP_STD_COMPLIANCE:
|
||||||
|
g_value_set_enum (value, ffmpegdec->std_compliance);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -69,6 +69,7 @@ struct _GstFFMpegVidDec
|
||||||
int max_threads;
|
int max_threads;
|
||||||
gboolean output_corrupt;
|
gboolean output_corrupt;
|
||||||
guint thread_type;
|
guint thread_type;
|
||||||
|
GstAvCodecCompliance std_compliance;
|
||||||
|
|
||||||
GstCaps *last_caps;
|
GstCaps *last_caps;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue