d3d11decoder: Check decoder status report

... and if h/w decoder reports error, increase error count.
This commit is contained in:
Seungha Yang 2020-02-26 15:55:23 +09:00
parent 26ac42f7c0
commit 418e6991c1
5 changed files with 170 additions and 3 deletions

View file

@ -1098,6 +1098,90 @@ gst_d3d11_decoder_copy_decoder_buffer (GstD3D11Decoder * decoder,
return copy_to_system (decoder, info, decoder_buffer, output);
}
static const gchar *
gst_d3d11_decoder_status_code_to_verbose_string (guint status_code)
{
const gchar *status = NULL;
switch (status_code) {
case 0:
status = "The operation succeeded";
break;
case 1:
status = "Minor problem in the data format. "
"The host decoder should continue processing";
break;
case 2:
status = "Significant problem in the data format. The host decoder may "
"continue executing or skip the display of the output picture";
break;
case 3:
status = "Severe problem in the data format. The host decoder should "
"restart the entire decoding process, starting at a sequence or "
"random-access entry point";
break;
case 4:
status =
"Other severe problem. The host decoder should restart the entire "
"decoding process, starting at a sequence or random-access entry point";
break;
default:
status = "Unknown status";
break;
}
return status;
}
gboolean
gst_d3d11_decoder_get_status_report (GstD3D11Decoder * decoder,
GstDXVAStatus * status, GError ** err)
{
GstD3D11DecoderPrivate *priv;
HRESULT hr;
D3D11_VIDEO_DECODER_EXTENSION extension = { 0, };
gboolean ret;
g_return_val_if_fail (GST_IS_D3D11_DECODER (decoder), FALSE);
g_return_val_if_fail (status != NULL, FALSE);
priv = decoder->priv;
/* For status report */
extension.Function = 7;
extension.pPrivateOutputData = (PVOID) status;
extension.PrivateOutputDataSize = sizeof (GstDXVAStatus);
gst_d3d11_device_lock (priv->device);
hr = ID3D11VideoContext_DecoderExtension (priv->video_context, priv->decoder,
&extension);
gst_d3d11_device_unlock (priv->device);
ret = gst_d3d11_result (hr, priv->device);
if (ret && status->bStatus != 0) {
/* TODO: if status code is 3 or 4, we might need to restart decoding
* from new keyframe */
GST_WARNING_OBJECT (decoder,
"Status code: %d, StatusReportFeedbackNumber: %d, "
"CurrPic.Index7Bits: %d, CurrPic.AssociatedFlag: %d, bBufType: %d, "
"wNumMbsAffected: %d", status->bStatus,
status->StatusReportFeedbackNumber,
status->CurrPic.Index7Bits, status->CurrPic.AssociatedFlag,
status->bBufType, status->wNumMbsAffected);
if (status->bStatus > 1) {
const gchar *status_str =
gst_d3d11_decoder_status_code_to_verbose_string (status->bStatus);
g_set_error_literal (err, GST_STREAM_ERROR,
GST_STREAM_ERROR_DECODE, status_str);
}
}
return ret;
}
/* Keep sync with chromium and keep in sorted order.
* See supported_profile_helpers.cc in chromium */
static const guint legacy_amd_list[] = {

View file

@ -41,6 +41,16 @@ G_BEGIN_DECLS
#define GST_IS_D3D11_DECODER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_D3D11_DECODER))
#define GST_D3D11_VIDEO_DECODER_ERROR_FROM_ERROR(el, err) G_STMT_START { \
gchar *__dbg = g_strdup (err->message); \
GstVideoDecoder *__dec = GST_VIDEO_DECODER (el); \
GST_WARNING_OBJECT (el, "error: %s", __dbg); \
_gst_video_decoder_error (__dec, 1, \
err->domain, err->code, \
NULL, __dbg, __FILE__, GST_FUNCTION, __LINE__); \
g_clear_error (&err); \
} G_STMT_END
typedef struct _GstD3D11DecoderOutputView GstD3D11DecoderOutputView;
struct _GstD3D11DecoderOutputView
@ -71,6 +81,35 @@ typedef struct
gchar *description;
} GstD3D11DecoderClassData;
/* use our struct for DXVA_Status_* (including DXVA_PicEntry_*) to query
* decoding status. Microsoft defines the struct per codec but their ABI are
* compatible each other and mingw header does not define some structs */
/* DXVA_PicEntry_*, from dxva.h */
typedef struct
{
union {
struct {
UCHAR Index7Bits : 7;
UCHAR AssociatedFlag : 1;
};
UCHAR bPicEntry;
};
} GstDXVAPicEntry;
/* DXVA_Status_*, from dxva.h */
typedef struct
{
UINT StatusReportFeedbackNumber;
GstDXVAPicEntry CurrPic; /* flag is bot field flag */
UCHAR field_pic_flag;
UCHAR bDXVA_Func;
UCHAR bBufType;
UCHAR bStatus;
UCHAR bReserved8Bits;
USHORT wNumMbsAffected;
} GstDXVAStatus;
struct _GstD3D11Decoder
{
GstObject parent;
@ -135,6 +174,10 @@ gboolean gst_d3d11_decoder_copy_decoder_buffer (GstD3D11Decoder * decod
GstBuffer * decoder_buffer,
GstBuffer * output);
gboolean gst_d3d11_decoder_get_status_report (GstD3D11Decoder * decoder,
GstDXVAStatus * status,
GError ** error);
/* Utils for class registration */
gboolean gst_d3d11_decoder_util_is_legacy_device (GstD3D11Device * device);

View file

@ -120,6 +120,8 @@ typedef struct _GstD3D11H264Dec
USHORT frame_num_list[16];
UINT used_for_reference_flags;
USHORT non_existing_frame_flags;
guint status_report_feedback_number;
} GstD3D11H264Dec;
typedef struct _GstD3D11H264DecClass
@ -557,6 +559,8 @@ gst_d3d11_h264_dec_new_sequence (GstH264Decoder * decoder,
GST_ERROR_OBJECT (self, "Failed to negotiate with downstream");
return FALSE;
}
self->status_report_feedback_number = 0;
}
return TRUE;
@ -915,6 +919,8 @@ gst_d3d11_h264_dec_end_picture (GstH264Decoder * decoder,
GstH264Picture * picture)
{
GstD3D11H264Dec *self = GST_D3D11_H264_DEC (decoder);
GError *err = NULL;
GstDXVAStatus status = { 0, };
GST_LOG_OBJECT (self, "end picture %p, (poc %d)",
picture, picture->pic_order_cnt);
@ -929,6 +935,11 @@ gst_d3d11_h264_dec_end_picture (GstH264Decoder * decoder,
return FALSE;
}
if (gst_d3d11_decoder_get_status_report (self->d3d11_decoder,
&status, &err) && err) {
GST_D3D11_VIDEO_DECODER_ERROR_FROM_ERROR (self, err);
}
return TRUE;
}
@ -1018,7 +1029,9 @@ gst_d3d11_h264_dec_fill_picture_params (GstD3D11H264Dec * self,
params->ContinuationFlag = 1;
params->Reserved8BitsA = 0;
params->Reserved8BitsB = 0;
params->StatusReportFeedbackNumber = 1;
/* StatusReportFeedbackNumber should be non-zero */
params->StatusReportFeedbackNumber = 1 + self->status_report_feedback_number;
self->status_report_feedback_number++;
gst_d3d11_h264_dec_picture_params_from_sps (self,
sps, slice_header->field_pic_flag, params);

View file

@ -89,6 +89,8 @@ typedef struct _GstD3D11H265Dec
UCHAR ref_pic_set_st_curr_before[8];
UCHAR ref_pic_set_st_curr_after[8];
UCHAR ref_pic_set_lt_curr[8];
guint status_report_feedback_number;
} GstD3D11H265Dec;
typedef struct _GstD3D11H265DecClass
@ -527,6 +529,8 @@ gst_d3d11_h265_dec_new_sequence (GstH265Decoder * decoder,
GST_ERROR_OBJECT (self, "Failed to negotiate with downstream");
return FALSE;
}
self->status_report_feedback_number = 0;
}
return TRUE;
@ -966,6 +970,8 @@ gst_d3d11_h265_dec_end_picture (GstH265Decoder * decoder,
GstH265Picture * picture)
{
GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder);
GError *err = NULL;
GstDXVAStatus status = { 0, };
GST_LOG_OBJECT (self, "end picture %p, (poc %d)",
picture, picture->pic_order_cnt);
@ -980,6 +986,11 @@ gst_d3d11_h265_dec_end_picture (GstH265Decoder * decoder,
return FALSE;
}
if (gst_d3d11_decoder_get_status_report (self->d3d11_decoder,
&status, &err) && err) {
GST_D3D11_VIDEO_DECODER_ERROR_FROM_ERROR (self, err);
}
return TRUE;
}
@ -1126,7 +1137,9 @@ gst_d3d11_h265_dec_fill_picture_params (GstD3D11H265Dec * self,
params->NoPicReorderingFlag = 0;
params->NoBiPredFlag = 0;
params->ReservedBits1 = 0;
params->StatusReportFeedbackNumber = 1;
/* StatusReportFeedbackNumber should be non-zero */
params->StatusReportFeedbackNumber = 1 + self->status_report_feedback_number;
self->status_report_feedback_number++;
gst_d3d11_h265_dec_picture_params_from_sps (self, sps, params);
gst_d3d11_h265_dec_picture_params_from_pps (self, pps, params);

View file

@ -102,6 +102,8 @@ typedef struct _GstD3D11Vp9Dec
GstVideoFormat out_format;
gboolean use_d3d11_output;
guint status_report_feedback_number;
} GstD3D11Vp9Dec;
typedef struct _GstD3D11Vp9DecClass
@ -498,6 +500,8 @@ gst_d3d11_vp9_dec_new_sequence (GstVp9Decoder * decoder,
GST_ERROR_OBJECT (self, "Failed to negotiate with downstream");
return FALSE;
}
self->status_report_feedback_number = 0;
}
return TRUE;
@ -1179,7 +1183,10 @@ gst_d3d11_vp9_dec_decode_picture (GstVp9Decoder * decoder,
pic_params.uncompressed_header_size_byte_aligned =
picture->frame_hdr.frame_header_length_in_bytes;
pic_params.first_partition_size = picture->frame_hdr.first_partition_size;
pic_params.StatusReportFeedbackNumber = 1;
/* StatusReportFeedbackNumber should be non-zero */
pic_params.StatusReportFeedbackNumber =
1 + self->status_report_feedback_number;
self->status_report_feedback_number++;
gst_d3d11_vp9_dec_copy_frame_params (self, picture, &pic_params);
gst_d3d11_vp9_dec_copy_reference_frames (self, picture, dpb, &pic_params);
@ -1195,12 +1202,19 @@ static gboolean
gst_d3d11_vp9_dec_end_picture (GstVp9Decoder * decoder, GstVp9Picture * picture)
{
GstD3D11Vp9Dec *self = GST_D3D11_VP9_DEC (decoder);
GError *err = NULL;
GstDXVAStatus status = { 0, };
if (!gst_d3d11_decoder_end_frame (self->d3d11_decoder)) {
GST_ERROR_OBJECT (self, "Failed to EndFrame");
return FALSE;
}
if (gst_d3d11_decoder_get_status_report (self->d3d11_decoder,
&status, &err) && err) {
GST_D3D11_VIDEO_DECODER_ERROR_FROM_ERROR (self, err);
}
return TRUE;
}