From: Haihao Xiang Date: Fri, 6 Dec 2019 04:48:37 +0000 (+0800) Subject: msdkh264dec: report error to user X-Git-Tag: 1.19.3~507^2~481 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5d891eb40c960552810f3220e93c637b8f6a3e4a;p=platform%2Fupstream%2Fgstreamer.git msdkh264dec: report error to user Sometimes user want to know what the error is when decoding a stream, This commit adds a property of report-error to msdkh264dec. When report-error is TRUE, msdkh264dec may catch bitstream error and frame corruption, then report the error to application by using GST_ELEMENT_ERROR Refer to the code in https://github.com/Intel-Media-SDK/MediaSDK/tree/master/samples Part-of: --- diff --git a/sys/msdk/gstmsdkdec.c b/sys/msdk/gstmsdkdec.c index da91f26..3c565ff 100644 --- a/sys/msdk/gstmsdkdec.c +++ b/sys/msdk/gstmsdkdec.c @@ -659,6 +659,37 @@ finish_task (GstMsdkDec * thiz, MsdkDecTask * task) task->decode_only = FALSE; } +static void +gst_msdkdec_frame_corruption_report (GstMsdkDec * thiz, mfxU16 corruption) +{ + if (!thiz->report_error || !corruption) + return; + + if (corruption & MFX_CORRUPTION_MINOR) + GST_ELEMENT_WARNING (thiz, STREAM, DECODE, + ("[Corruption] Minor corruption detected!"), (NULL)); + + if (corruption & MFX_CORRUPTION_MAJOR) + GST_ELEMENT_WARNING (thiz, STREAM, DECODE, + ("[Corruption] Major corruption detected!"), (NULL)); + + if (corruption & MFX_CORRUPTION_ABSENT_TOP_FIELD) + GST_ELEMENT_WARNING (thiz, STREAM, DECODE, + ("[Corruption] Absent top field!"), (NULL)); + + if (corruption & MFX_CORRUPTION_ABSENT_BOTTOM_FIELD) + GST_ELEMENT_WARNING (thiz, STREAM, DECODE, + ("[Corruption] Absent bottom field!"), (NULL)); + + if (corruption & MFX_CORRUPTION_REFERENCE_FRAME) + GST_ELEMENT_WARNING (thiz, STREAM, DECODE, + ("[Corruption] Corrupted reference frame!"), (NULL)); + + if (corruption & MFX_CORRUPTION_REFERENCE_LIST) + GST_ELEMENT_WARNING (thiz, STREAM, DECODE, + ("[Corruption] Corrupted reference list!"), (NULL)); +} + static GstFlowReturn gst_msdkdec_finish_task (GstMsdkDec * thiz, MsdkDecTask * task) { @@ -681,6 +712,8 @@ gst_msdkdec_finish_task (GstMsdkDec * thiz, MsdkDecTask * task) surface = task->surface; if (surface) { + gst_msdkdec_frame_corruption_report (thiz, + surface->surface->Data.Corrupted); GST_DEBUG_OBJECT (thiz, "Decoded MFX TimeStamp: %" G_GUINT64_FORMAT, (guint64) surface->surface->Data.TimeStamp); pts = surface->surface->Data.TimeStamp; @@ -984,6 +1017,33 @@ find_msdk_surface (GstMsdkDec * thiz, MsdkDecTask * task, return TRUE; } +static void +gst_msdkdec_error_report (GstMsdkDec * thiz) +{ + if (!thiz->report_error) + return; + +#if (MFX_VERSION >= 1025) + else { + if (thiz->error_report.ErrorTypes & MFX_ERROR_SPS) + GST_ELEMENT_WARNING (thiz, STREAM, DECODE, + ("[Error] SPS Error detected!"), (NULL)); + + if (thiz->error_report.ErrorTypes & MFX_ERROR_PPS) + GST_ELEMENT_WARNING (thiz, STREAM, DECODE, + ("[Error] PPS Error detected!"), (NULL)); + + if (thiz->error_report.ErrorTypes & MFX_ERROR_SLICEHEADER) + GST_ELEMENT_WARNING (thiz, STREAM, DECODE, + ("[Error] SliceHeader Error detected!"), (NULL)); + + if (thiz->error_report.ErrorTypes & MFX_ERROR_FRAME_GAP) + GST_ELEMENT_WARNING (thiz, STREAM, DECODE, + ("[Error] Frame Gap Error detected!"), (NULL)); + } +#endif +} + static GstFlowReturn gst_msdkdec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame) { @@ -1093,8 +1153,15 @@ gst_msdkdec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame) * and this information can't be retrieved from the negotiated caps. * So instead of introducing a codecparser dependency to parse the headers * inside msdk plugin, we simply use the mfx APIs to extract header information */ +#if (MFX_VERSION >= 1025) + if (thiz->report_error) + thiz->error_report.ErrorTypes = 0; +#endif + status = MFXVideoDECODE_DecodeHeader (session, &bitstream, &thiz->param); GST_DEBUG_OBJECT (decoder, "DecodeHeader => %d", status); + gst_msdkdec_error_report (thiz); + if (status == MFX_ERR_MORE_DATA) { flow = GST_FLOW_OK; goto done; @@ -1179,6 +1246,10 @@ gst_msdkdec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame) } } } +#if (MFX_VERSION >= 1025) + if (thiz->report_error) + thiz->error_report.ErrorTypes = 0; +#endif status = MFXVideoDECODE_DecodeFrameAsync (session, &bitstream, surface->surface, @@ -1190,6 +1261,7 @@ gst_msdkdec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame) } GST_DEBUG_OBJECT (decoder, "DecodeFrameAsync => %d", status); + gst_msdkdec_error_report (thiz); /* media-sdk requires complete reset since the surface is inadequate * for further decoding */ @@ -1199,8 +1271,14 @@ gst_msdkdec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame) * suitable for the current frame. Call MFXVideoDECODE_DecodeHeader to get * the current frame size, then do memory re-allocation, otherwise * MFXVideoDECODE_DecodeFrameAsync will still fail on next call */ +#if (MFX_VERSION >= 1025) + if (thiz->report_error) + thiz->error_report.ErrorTypes = 0; +#endif status = MFXVideoDECODE_DecodeHeader (session, &bitstream, &thiz->param); GST_DEBUG_OBJECT (decoder, "DecodeHeader => %d", status); + gst_msdkdec_error_report (thiz); + if (status == MFX_ERR_MORE_DATA) { flow = GST_FLOW_OK; goto done; @@ -1574,6 +1652,10 @@ gst_msdkdec_drain (GstVideoDecoder * decoder) if (!surface) return GST_FLOW_ERROR; } +#if (MFX_VERSION >= 1025) + if (thiz->report_error) + thiz->error_report.ErrorTypes = 0; +#endif status = MFXVideoDECODE_DecodeFrameAsync (session, NULL, surface->surface, @@ -1584,6 +1666,8 @@ gst_msdkdec_drain (GstVideoDecoder * decoder) } GST_DEBUG_OBJECT (decoder, "DecodeFrameAsync => %d", status); + gst_msdkdec_error_report (thiz); + if (G_LIKELY (status == MFX_ERR_NONE)) { thiz->next_task = (thiz->next_task + 1) % thiz->tasks->len; surface = NULL; @@ -1818,6 +1902,7 @@ gst_msdkdec_init (GstMsdkDec * thiz) thiz->do_renego = TRUE; thiz->do_realloc = TRUE; thiz->force_reset_on_res_change = TRUE; + thiz->report_error = FALSE; thiz->adapter = gst_adapter_new (); thiz->input_state = NULL; thiz->pool = NULL; diff --git a/sys/msdk/gstmsdkdec.h b/sys/msdk/gstmsdkdec.h index 7bde77d..638edfb 100644 --- a/sys/msdk/gstmsdkdec.h +++ b/sys/msdk/gstmsdkdec.h @@ -99,10 +99,15 @@ struct _GstMsdkDec /* element properties */ gboolean hardware; + gboolean report_error; guint async_depth; mfxExtBuffer *bs_extra_params[MAX_BS_EXTRA_PARAMS]; guint num_bs_extra_params; + +#if (MFX_VERSION >= 1025) + mfxExtDecodeErrorReport error_report; +#endif }; struct _GstMsdkDecClass diff --git a/sys/msdk/gstmsdkdecproputil.c b/sys/msdk/gstmsdkdecproputil.c index 5efb0de..f77e22f 100644 --- a/sys/msdk/gstmsdkdecproputil.c +++ b/sys/msdk/gstmsdkdecproputil.c @@ -42,6 +42,16 @@ gst_msdkdec_prop_install_output_oder_property (GObjectClass * gobject_class) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } +void +gst_msdkdec_prop_install_error_report_property (GObjectClass * gobject_class) +{ + g_object_class_install_property (gobject_class, GST_MSDKDEC_PROP_ERROR_REPORT, + g_param_spec_boolean ("report-error", "report-error", + "Report bitstream error information", + PROP_ERROR_REPORT_DEFAULT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +} + gboolean gst_msdkdec_prop_check_state (GstState state, GParamSpec * pspec) { diff --git a/sys/msdk/gstmsdkdecproputil.h b/sys/msdk/gstmsdkdecproputil.h index d24abd1..5ca887e 100644 --- a/sys/msdk/gstmsdkdecproputil.h +++ b/sys/msdk/gstmsdkdecproputil.h @@ -37,6 +37,7 @@ G_BEGIN_DECLS #define PROP_OUTPUT_ORDER_DEFAULT GST_MSDKDEC_OUTPUT_ORDER_DISPLAY +#define PROP_ERROR_REPORT_DEFAULT FALSE enum { @@ -44,11 +45,15 @@ enum GST_MSDKDEC_PROP_HARDWARE, GST_MSDKDEC_PROP_ASYNC_DEPTH, GST_MSDKDEC_PROP_OUTPUT_ORDER, + GST_MSDKDEC_PROP_ERROR_REPORT, }; void gst_msdkdec_prop_install_output_oder_property(GObjectClass * gobject_class); +void +gst_msdkdec_prop_install_error_report_property (GObjectClass * gobject_class); + gboolean gst_msdkdec_prop_check_state(GstState state, GParamSpec * pspec); diff --git a/sys/msdk/gstmsdkh264dec.c b/sys/msdk/gstmsdkh264dec.c index caeda8e..9b66126 100644 --- a/sys/msdk/gstmsdkh264dec.c +++ b/sys/msdk/gstmsdkh264dec.c @@ -61,6 +61,17 @@ gst_msdkh264dec_configure (GstMsdkDec * decoder) * customers still using this for low-latency streaming of non-b-frame * encoded streams */ decoder->param.mfx.DecodedOrder = h264dec->output_order; + +#if (MFX_VERSION >= 1025) + if (decoder->report_error) { + decoder->error_report.Header.BufferId = MFX_EXTBUFF_DECODE_ERROR_REPORT; + decoder->error_report.Header.BufferSz = sizeof (decoder->error_report); + decoder->error_report.ErrorTypes = 0; + gst_msdkdec_add_bs_extra_param (decoder, + (mfxExtBuffer *) & decoder->error_report); + } +#endif + return TRUE; } @@ -69,6 +80,9 @@ gst_msdkdec_h264_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstMsdkH264Dec *thiz = GST_MSDKH264DEC (object); +#if (MFX_VERSION >= 1025) + GstMsdkDec *dec = GST_MSDKDEC (object); +#endif GstState state; GST_OBJECT_LOCK (thiz); @@ -83,6 +97,11 @@ gst_msdkdec_h264_set_property (GObject * object, guint prop_id, case GST_MSDKDEC_PROP_OUTPUT_ORDER: thiz->output_order = g_value_get_enum (value); break; +#if (MFX_VERSION >= 1025) + case GST_MSDKDEC_PROP_ERROR_REPORT: + dec->report_error = g_value_get_boolean (value); + break; +#endif default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -96,12 +115,20 @@ gst_msdkdec_h264_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstMsdkH264Dec *thiz = GST_MSDKH264DEC (object); +#if (MFX_VERSION >= 1025) + GstMsdkDec *dec = GST_MSDKDEC (object); +#endif GST_OBJECT_LOCK (thiz); switch (prop_id) { case GST_MSDKDEC_PROP_OUTPUT_ORDER: g_value_set_enum (value, thiz->output_order); break; +#if (MFX_VERSION >= 1025) + case GST_MSDKDEC_PROP_ERROR_REPORT: + g_value_set_boolean (value, dec->report_error); + break; +#endif default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -133,6 +160,10 @@ gst_msdkh264dec_class_init (GstMsdkH264DecClass * klass) gst_msdkdec_prop_install_output_oder_property (gobject_class); +#if (MFX_VERSION >= 1025) + gst_msdkdec_prop_install_error_report_property (gobject_class); +#endif + gst_element_class_add_static_pad_template (element_class, &sink_factory); }