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;
+}
#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
{
PROP_MAX_THREADS,
PROP_OUTPUT_CORRUPT,
PROP_THREAD_TYPE,
+ PROP_STD_COMPLIANCE,
PROP_LAST
};
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;
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
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));
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
} 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;
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;
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;