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);
|
||||
}
|
||||
|
||||
|
||||
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 *
|
||||
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__ */
|
||||
|
|
|
@ -48,6 +48,7 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
|
|||
#define DEFAULT_STRIDE_ALIGN 31
|
||||
#define DEFAULT_ALLOC_PARAM { 0, DEFAULT_STRIDE_ALIGN, 0, 0, }
|
||||
#define DEFAULT_THREAD_TYPE 0
|
||||
#define DEFAULT_STD_COMPLIANCE GST_AV_CODEC_COMPLIANCE_AUTO
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -59,6 +60,7 @@ enum
|
|||
PROP_MAX_THREADS,
|
||||
PROP_OUTPUT_CORRUPT,
|
||||
PROP_THREAD_TYPE,
|
||||
PROP_STD_COMPLIANCE,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
|
@ -293,6 +295,18 @@ gst_ffmpegviddec_class_init (GstFFMpegVidDecClass * klass)
|
|||
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->handle_frame = gst_ffmpegviddec_handle_frame;
|
||||
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_SKIPFRAME, 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
|
||||
|
@ -492,6 +507,8 @@ gst_ffmpegviddec_set_format (GstVideoDecoder * decoder,
|
|||
GstFFMpegVidDecClass *oclass;
|
||||
GstClockTime latency = GST_CLOCK_TIME_NONE;
|
||||
gboolean ret = FALSE;
|
||||
gboolean is_live;
|
||||
GstQuery *query;
|
||||
|
||||
ffmpegdec = (GstFFMpegVidDec *) decoder;
|
||||
oclass = (GstFFMpegVidDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));
|
||||
|
@ -568,23 +585,21 @@ gst_ffmpegviddec_set_format (GstVideoDecoder * decoder,
|
|||
ffmpegdec->context->lowres = ffmpegdec->lowres;
|
||||
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) {
|
||||
GST_DEBUG_OBJECT (ffmpegdec, "Use requested thread type 0x%x",
|
||||
ffmpegdec->thread_type);
|
||||
ffmpegdec->context->thread_type = ffmpegdec->thread_type;
|
||||
} 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)
|
||||
ffmpegdec->context->thread_type = FF_THREAD_SLICE;
|
||||
else
|
||||
|
@ -603,6 +618,19 @@ gst_ffmpegviddec_set_format (GstVideoDecoder * decoder,
|
|||
} else
|
||||
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) {
|
||||
GstStructure *s = gst_caps_get_structure (state->caps, 0);
|
||||
const char *alignment;
|
||||
|
@ -2417,6 +2445,9 @@ gst_ffmpegviddec_set_property (GObject * object,
|
|||
case PROP_THREAD_TYPE:
|
||||
ffmpegdec->thread_type = g_value_get_flags (value);
|
||||
break;
|
||||
case PROP_STD_COMPLIANCE:
|
||||
ffmpegdec->std_compliance = g_value_get_enum (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -2453,6 +2484,9 @@ gst_ffmpegviddec_get_property (GObject * object,
|
|||
case PROP_THREAD_TYPE:
|
||||
g_value_set_flags (value, ffmpegdec->thread_type);
|
||||
break;
|
||||
case PROP_STD_COMPLIANCE:
|
||||
g_value_set_enum (value, ffmpegdec->std_compliance);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
|
|
@ -69,6 +69,7 @@ struct _GstFFMpegVidDec
|
|||
int max_threads;
|
||||
gboolean output_corrupt;
|
||||
guint thread_type;
|
||||
GstAvCodecCompliance std_compliance;
|
||||
|
||||
GstCaps *last_caps;
|
||||
|
||||
|
|
Loading…
Reference in a new issue