d3d11h{264,265}dec: Submit picture level parameters only once

Submit PICTURE_PARAMETERS and INVERSE_QUANTIZATION_MATRIX
buffers only once per picture. Multiple submission is redundant.
Also this modification would fix broken hevc decoding with
dependent slice.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1749>
This commit is contained in:
Seungha Yang 2020-11-01 20:52:11 +09:00 committed by GStreamer Merge Bot
parent eeffd91109
commit 337cb883fa
2 changed files with 226 additions and 230 deletions

View file

@ -161,6 +161,8 @@ static gboolean gst_d3d11_h264_dec_decode_slice (GstH264Decoder * decoder,
GArray * ref_pic_list1);
static gboolean gst_d3d11_h264_dec_end_picture (GstH264Decoder * decoder,
GstH264Picture * picture);
static gboolean gst_d3d11_h264_dec_fill_picture_params (GstD3D11H264Dec * self,
const GstH264SliceHdr * slice_header, DXVA_PicParams_H264 * params);
static void
gst_d3d11_h264_dec_class_init (GstD3D11H264DecClass * klass, gpointer data)
@ -519,8 +521,20 @@ gst_d3d11_h264_dec_start_picture (GstH264Decoder * decoder,
{
GstD3D11H264Dec *self = GST_D3D11_H264_DEC (decoder);
ID3D11VideoDecoderOutputView *view;
gint i;
GArray *dpb_array;
GstH264SPS *sps;
GstH264PPS *pps;
DXVA_PicParams_H264 pic_params = { 0, };
DXVA_Qmatrix_H264 iq_matrix = { 0, };
guint d3d11_buffer_size = 0;
gpointer d3d11_buffer = NULL;
gint i, j;
pps = slice->header.pps;
g_assert (pps != NULL);
sps = pps->sequence;
g_assert (sps != NULL);
view = gst_d3d11_h264_dec_get_output_view_from_picture (self, picture);
if (!view) {
@ -529,7 +543,6 @@ gst_d3d11_h264_dec_start_picture (GstH264Decoder * decoder,
}
GST_TRACE_OBJECT (self, "Begin frame");
if (!gst_d3d11_decoder_begin_frame (self->d3d11_decoder, view, 0, NULL)) {
GST_ERROR_OBJECT (self, "Failed to begin frame");
return FALSE;
@ -570,6 +583,96 @@ gst_d3d11_h264_dec_start_picture (GstH264Decoder * decoder,
self->non_existing_frame_flags |= (other->nonexisting) << i;
}
gst_d3d11_h264_dec_fill_picture_params (self, &slice->header, &pic_params);
pic_params.CurrPic.Index7Bits =
gst_d3d11_decoder_get_output_view_index (view);
pic_params.RefPicFlag = picture->ref;
pic_params.frame_num = picture->frame_num;
if (pic_params.field_pic_flag && pic_params.CurrPic.AssociatedFlag) {
pic_params.CurrFieldOrderCnt[1] = picture->bottom_field_order_cnt;
pic_params.CurrFieldOrderCnt[0] = 0;
} else if (pic_params.field_pic_flag && !pic_params.CurrPic.AssociatedFlag) {
pic_params.CurrFieldOrderCnt[0] = picture->top_field_order_cnt;
pic_params.CurrFieldOrderCnt[1] = 0;
} else {
pic_params.CurrFieldOrderCnt[0] = picture->top_field_order_cnt;
pic_params.CurrFieldOrderCnt[1] = picture->bottom_field_order_cnt;
}
memcpy (pic_params.RefFrameList, self->ref_frame_list,
sizeof (pic_params.RefFrameList));
memcpy (pic_params.FieldOrderCntList, self->field_order_cnt_list,
sizeof (pic_params.FieldOrderCntList));
memcpy (pic_params.FrameNumList, self->frame_num_list,
sizeof (pic_params.FrameNumList));
pic_params.UsedForReferenceFlags = self->used_for_reference_flags;
pic_params.NonExistingFrameFlags = self->non_existing_frame_flags;
GST_TRACE_OBJECT (self, "Getting picture param decoder buffer");
if (!gst_d3d11_decoder_get_decoder_buffer (self->d3d11_decoder,
D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS, &d3d11_buffer_size,
&d3d11_buffer)) {
GST_ERROR_OBJECT (self,
"Failed to get decoder buffer for picture parameters");
return FALSE;
}
memcpy (d3d11_buffer, &pic_params, sizeof (DXVA_PicParams_H264));
GST_TRACE_OBJECT (self, "Release picture param decoder buffer");
if (!gst_d3d11_decoder_release_decoder_buffer (self->d3d11_decoder,
D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS)) {
GST_ERROR_OBJECT (self, "Failed to release decoder buffer");
return FALSE;
}
if (pps->pic_scaling_matrix_present_flag) {
for (i = 0; i < 6; i++) {
for (j = 0; j < 16; j++) {
iq_matrix.bScalingLists4x4[i][j] = pps->scaling_lists_4x4[i][j];
}
}
for (i = 0; i < 2; i++) {
for (j = 0; j < 64; j++) {
iq_matrix.bScalingLists8x8[i][j] = pps->scaling_lists_8x8[i][j];
}
}
} else {
for (i = 0; i < 6; i++) {
for (j = 0; j < 16; j++) {
iq_matrix.bScalingLists4x4[i][j] = sps->scaling_lists_4x4[i][j];
}
}
for (i = 0; i < 2; i++) {
for (j = 0; j < 64; j++) {
iq_matrix.bScalingLists8x8[i][j] = sps->scaling_lists_8x8[i][j];
}
}
}
GST_TRACE_OBJECT (self, "Getting inverse quantization matrix buffer");
if (!gst_d3d11_decoder_get_decoder_buffer (self->d3d11_decoder,
D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX,
&d3d11_buffer_size, &d3d11_buffer)) {
GST_ERROR_OBJECT (self,
"Failed to get decoder buffer for inv. quantization matrix");
return FALSE;
}
memcpy (d3d11_buffer, &iq_matrix, sizeof (DXVA_Qmatrix_H264));
GST_TRACE_OBJECT (self, "Release inverse quantization matrix buffer");
if (!gst_d3d11_decoder_release_decoder_buffer (self->d3d11_decoder,
D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX)) {
GST_ERROR_OBJECT (self, "Failed to release decoder buffer");
return FALSE;
}
g_array_unref (dpb_array);
g_array_set_size (self->slice_list, 0);
@ -894,118 +997,6 @@ gst_d3d11_h264_dec_decode_slice (GstH264Decoder * decoder,
GArray * ref_pic_list1)
{
GstD3D11H264Dec *self = GST_D3D11_H264_DEC (decoder);
GstH264SPS *sps;
GstH264PPS *pps;
DXVA_PicParams_H264 pic_params = { 0, };
DXVA_Qmatrix_H264 iq_matrix = { 0, };
guint d3d11_buffer_size = 0;
gpointer d3d11_buffer = NULL;
gint i, j;
ID3D11VideoDecoderOutputView *view;
pps = slice->header.pps;
sps = pps->sequence;
view = gst_d3d11_h264_dec_get_output_view_from_picture (self, picture);
if (!view) {
GST_ERROR_OBJECT (self, "current picture does not have output view");
return FALSE;
}
gst_d3d11_h264_dec_fill_picture_params (self, &slice->header, &pic_params);
pic_params.CurrPic.Index7Bits =
gst_d3d11_decoder_get_output_view_index (view);
pic_params.RefPicFlag = picture->ref;
pic_params.frame_num = picture->frame_num;
if (pic_params.field_pic_flag && pic_params.CurrPic.AssociatedFlag) {
pic_params.CurrFieldOrderCnt[1] = picture->bottom_field_order_cnt;
pic_params.CurrFieldOrderCnt[0] = 0;
} else if (pic_params.field_pic_flag && !pic_params.CurrPic.AssociatedFlag) {
pic_params.CurrFieldOrderCnt[0] = picture->top_field_order_cnt;
pic_params.CurrFieldOrderCnt[1] = 0;
} else {
pic_params.CurrFieldOrderCnt[0] = picture->top_field_order_cnt;
pic_params.CurrFieldOrderCnt[1] = picture->bottom_field_order_cnt;
}
memcpy (pic_params.RefFrameList, self->ref_frame_list,
sizeof (pic_params.RefFrameList));
memcpy (pic_params.FieldOrderCntList, self->field_order_cnt_list,
sizeof (pic_params.FieldOrderCntList));
memcpy (pic_params.FrameNumList, self->frame_num_list,
sizeof (pic_params.FrameNumList));
pic_params.UsedForReferenceFlags = self->used_for_reference_flags;
pic_params.NonExistingFrameFlags = self->non_existing_frame_flags;
GST_TRACE_OBJECT (self, "Getting picture param decoder buffer");
if (!gst_d3d11_decoder_get_decoder_buffer (self->d3d11_decoder,
D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS, &d3d11_buffer_size,
&d3d11_buffer)) {
GST_ERROR_OBJECT (self,
"Failed to get decoder buffer for picture parameters");
return FALSE;
}
memcpy (d3d11_buffer, &pic_params, sizeof (DXVA_PicParams_H264));
GST_TRACE_OBJECT (self, "Release picture param decoder buffer");
if (!gst_d3d11_decoder_release_decoder_buffer (self->d3d11_decoder,
D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS)) {
GST_ERROR_OBJECT (self, "Failed to release decoder buffer");
return FALSE;
}
if (pps->pic_scaling_matrix_present_flag) {
for (i = 0; i < 6; i++) {
for (j = 0; j < 16; j++) {
iq_matrix.bScalingLists4x4[i][j] = pps->scaling_lists_4x4[i][j];
}
}
for (i = 0; i < 2; i++) {
for (j = 0; j < 64; j++) {
iq_matrix.bScalingLists8x8[i][j] = pps->scaling_lists_8x8[i][j];
}
}
} else {
for (i = 0; i < 6; i++) {
for (j = 0; j < 16; j++) {
iq_matrix.bScalingLists4x4[i][j] = sps->scaling_lists_4x4[i][j];
}
}
for (i = 0; i < 2; i++) {
for (j = 0; j < 64; j++) {
iq_matrix.bScalingLists8x8[i][j] = sps->scaling_lists_8x8[i][j];
}
}
}
GST_TRACE_OBJECT (self, "Getting inverse quantization maxtirx buffer");
if (!gst_d3d11_decoder_get_decoder_buffer (self->d3d11_decoder,
D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX,
&d3d11_buffer_size, &d3d11_buffer)) {
GST_ERROR_OBJECT (self,
"Failed to get decoder buffer for inv. quantization matrix");
return FALSE;
}
memcpy (d3d11_buffer, &iq_matrix, sizeof (DXVA_Qmatrix_H264));
GST_TRACE_OBJECT (self, "Release inverse quantization maxtirx buffer");
if (!gst_d3d11_decoder_release_decoder_buffer (self->d3d11_decoder,
D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX)) {
GST_ERROR_OBJECT (self, "Failed to release decoder buffer");
return FALSE;
}
{
guint to_write = slice->nalu.size + 3;

View file

@ -130,6 +130,14 @@ static gboolean gst_d3d11_h265_dec_decode_slice (GstH265Decoder * decoder,
GArray * ref_pic_list0, GArray * ref_pic_list1);
static gboolean gst_d3d11_h265_dec_end_picture (GstH265Decoder * decoder,
GstH265Picture * picture);
static gboolean gst_d3d11_h265_dec_fill_picture_params (GstD3D11H265Dec * self,
const GstH265SliceHdr * slice_header, DXVA_PicParams_HEVC * params);
#ifndef GST_DISABLE_GST_DEBUG
static void
gst_d3d11_h265_dec_dump_pic_params (GstD3D11H265Dec * self,
DXVA_PicParams_HEVC * params);
#endif
static void
gst_d3d11_h265_dec_class_init (GstD3D11H265DecClass * klass, gpointer data)
@ -502,6 +510,19 @@ gst_d3d11_h265_dec_start_picture (GstH265Decoder * decoder,
ID3D11VideoDecoderOutputView *view;
gint i, j;
GArray *dpb_array;
GstH265SPS *sps;
GstH265PPS *pps;
DXVA_PicParams_HEVC pic_params = { 0, };
DXVA_Qmatrix_HEVC iq_matrix = { 0, };
GstH265ScalingList *scaling_list = NULL;
guint d3d11_buffer_size = 0;
gpointer d3d11_buffer = NULL;
pps = slice->header.pps;
g_assert (pps != NULL);
sps = pps->sps;
g_assert (sps != NULL);
view = gst_d3d11_h265_dec_get_output_view_from_picture (self, picture);
if (!view) {
@ -510,7 +531,6 @@ gst_d3d11_h265_dec_start_picture (GstH265Decoder * decoder,
}
GST_TRACE_OBJECT (self, "Begin frame");
if (!gst_d3d11_decoder_begin_frame (self->d3d11_decoder, view, 0, NULL)) {
GST_ERROR_OBJECT (self, "Failed to begin frame");
return FALSE;
@ -617,6 +637,106 @@ gst_d3d11_h265_dec_start_picture (GstH265Decoder * decoder,
self->ref_pic_set_lt_curr[i] = id;
}
view = gst_d3d11_h265_dec_get_output_view_from_picture (self, picture);
if (!view) {
GST_ERROR_OBJECT (self, "current picture does not have output view");
return FALSE;
}
gst_d3d11_h265_dec_fill_picture_params (self, &slice->header, &pic_params);
pic_params.CurrPic.Index7Bits =
gst_d3d11_decoder_get_output_view_index (view);
pic_params.IrapPicFlag = GST_H265_IS_NAL_TYPE_IRAP (slice->nalu.type);
pic_params.IdrPicFlag = GST_H265_IS_NAL_TYPE_IDR (slice->nalu.type);
pic_params.IntraPicFlag = GST_H265_IS_NAL_TYPE_IRAP (slice->nalu.type);
pic_params.CurrPicOrderCntVal = picture->pic_order_cnt;
memcpy (pic_params.RefPicList, self->ref_pic_list,
sizeof (pic_params.RefPicList));
memcpy (pic_params.PicOrderCntValList, self->pic_order_cnt_val_list,
sizeof (pic_params.PicOrderCntValList));
memcpy (pic_params.RefPicSetStCurrBefore, self->ref_pic_set_st_curr_before,
sizeof (pic_params.RefPicSetStCurrBefore));
memcpy (pic_params.RefPicSetStCurrAfter, self->ref_pic_set_st_curr_after,
sizeof (pic_params.RefPicSetStCurrAfter));
memcpy (pic_params.RefPicSetLtCurr, self->ref_pic_set_lt_curr,
sizeof (pic_params.RefPicSetLtCurr));
#ifndef GST_DISABLE_GST_DEBUG
if (gst_debug_category_get_threshold (GST_CAT_DEFAULT) >= GST_LEVEL_TRACE)
gst_d3d11_h265_dec_dump_pic_params (self, &pic_params);
#endif
GST_TRACE_OBJECT (self, "Getting picture param decoder buffer");
if (!gst_d3d11_decoder_get_decoder_buffer (self->d3d11_decoder,
D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS, &d3d11_buffer_size,
&d3d11_buffer)) {
GST_ERROR_OBJECT (self,
"Failed to get decoder buffer for picture parameters");
return FALSE;
}
memcpy (d3d11_buffer, &pic_params, sizeof (pic_params));
GST_TRACE_OBJECT (self, "Release picture param decoder buffer");
if (!gst_d3d11_decoder_release_decoder_buffer (self->d3d11_decoder,
D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS)) {
GST_ERROR_OBJECT (self, "Failed to release decoder buffer");
return FALSE;
}
if (pps->scaling_list_data_present_flag ||
(sps->scaling_list_enabled_flag
&& !sps->scaling_list_data_present_flag)) {
scaling_list = &pps->scaling_list;
} else if (sps->scaling_list_enabled_flag &&
sps->scaling_list_data_present_flag) {
scaling_list = &sps->scaling_list;
}
if (scaling_list) {
self->submit_iq_data = TRUE;
memcpy (iq_matrix.ucScalingLists0, scaling_list->scaling_lists_4x4,
sizeof (iq_matrix.ucScalingLists0));
memcpy (iq_matrix.ucScalingLists1, scaling_list->scaling_lists_8x8,
sizeof (iq_matrix.ucScalingLists1));
memcpy (iq_matrix.ucScalingLists2, scaling_list->scaling_lists_16x16,
sizeof (iq_matrix.ucScalingLists2));
memcpy (iq_matrix.ucScalingLists3, scaling_list->scaling_lists_32x32,
sizeof (iq_matrix.ucScalingLists3));
for (i = 0; i < 6; i++)
iq_matrix.ucScalingListDCCoefSizeID2[i] =
scaling_list->scaling_list_dc_coef_minus8_16x16[i] + 8;
for (i = 0; i < 2; i++)
iq_matrix.ucScalingListDCCoefSizeID3[i] =
scaling_list->scaling_list_dc_coef_minus8_32x32[i] + 8;
GST_TRACE_OBJECT (self, "Getting inverse quantization matrix buffer");
if (!gst_d3d11_decoder_get_decoder_buffer (self->d3d11_decoder,
D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX,
&d3d11_buffer_size, &d3d11_buffer)) {
GST_ERROR_OBJECT (self,
"Failed to get decoder buffer for inv. quantization matrix");
return FALSE;
}
memcpy (d3d11_buffer, &iq_matrix, sizeof (iq_matrix));
GST_TRACE_OBJECT (self, "Release inverse quantization matrix buffer");
if (!gst_d3d11_decoder_release_decoder_buffer (self->d3d11_decoder,
D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX)) {
GST_ERROR_OBJECT (self, "Failed to release decoder buffer");
return FALSE;
}
} else {
self->submit_iq_data = FALSE;
}
g_array_unref (dpb_array);
g_array_set_size (self->slice_list, 0);
@ -1117,121 +1237,6 @@ gst_d3d11_h265_dec_decode_slice (GstH265Decoder * decoder,
GArray * ref_pic_list0, GArray * ref_pic_list1)
{
GstD3D11H265Dec *self = GST_D3D11_H265_DEC (decoder);
GstH265SPS *sps;
GstH265PPS *pps;
DXVA_PicParams_HEVC pic_params = { 0, };
DXVA_Qmatrix_HEVC iq_matrix = { 0, };
guint d3d11_buffer_size = 0;
gpointer d3d11_buffer = NULL;
gint i;
ID3D11VideoDecoderOutputView *view;
GstH265ScalingList *scaling_list = NULL;
pps = slice->header.pps;
sps = pps->sps;
view = gst_d3d11_h265_dec_get_output_view_from_picture (self, picture);
if (!view) {
GST_ERROR_OBJECT (self, "current picture does not have output view");
return FALSE;
}
gst_d3d11_h265_dec_fill_picture_params (self, &slice->header, &pic_params);
pic_params.CurrPic.Index7Bits =
gst_d3d11_decoder_get_output_view_index (view);
pic_params.IrapPicFlag = GST_H265_IS_NAL_TYPE_IRAP (slice->nalu.type);
pic_params.IdrPicFlag = GST_H265_IS_NAL_TYPE_IDR (slice->nalu.type);
pic_params.IntraPicFlag = GST_H265_IS_NAL_TYPE_IRAP (slice->nalu.type);
pic_params.CurrPicOrderCntVal = picture->pic_order_cnt;
memcpy (pic_params.RefPicList, self->ref_pic_list,
sizeof (pic_params.RefPicList));
memcpy (pic_params.PicOrderCntValList, self->pic_order_cnt_val_list,
sizeof (pic_params.PicOrderCntValList));
memcpy (pic_params.RefPicSetStCurrBefore, self->ref_pic_set_st_curr_before,
sizeof (pic_params.RefPicSetStCurrBefore));
memcpy (pic_params.RefPicSetStCurrAfter, self->ref_pic_set_st_curr_after,
sizeof (pic_params.RefPicSetStCurrAfter));
memcpy (pic_params.RefPicSetLtCurr, self->ref_pic_set_lt_curr,
sizeof (pic_params.RefPicSetLtCurr));
#ifndef GST_DISABLE_GST_DEBUG
gst_d3d11_h265_dec_dump_pic_params (self, &pic_params);
#endif
GST_TRACE_OBJECT (self, "Getting picture param decoder buffer");
if (!gst_d3d11_decoder_get_decoder_buffer (self->d3d11_decoder,
D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS, &d3d11_buffer_size,
&d3d11_buffer)) {
GST_ERROR_OBJECT (self,
"Failed to get decoder buffer for picture parameters");
return FALSE;
}
memcpy (d3d11_buffer, &pic_params, sizeof (pic_params));
GST_TRACE_OBJECT (self, "Release picture param decoder buffer");
if (!gst_d3d11_decoder_release_decoder_buffer (self->d3d11_decoder,
D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS)) {
GST_ERROR_OBJECT (self, "Failed to release decoder buffer");
return FALSE;
}
if (pps->scaling_list_data_present_flag ||
(sps->scaling_list_enabled_flag
&& !sps->scaling_list_data_present_flag)) {
scaling_list = &pps->scaling_list;
} else if (sps->scaling_list_enabled_flag &&
sps->scaling_list_data_present_flag) {
scaling_list = &sps->scaling_list;
}
if (scaling_list) {
self->submit_iq_data = TRUE;
memcpy (iq_matrix.ucScalingLists0, scaling_list->scaling_lists_4x4,
sizeof (iq_matrix.ucScalingLists0));
memcpy (iq_matrix.ucScalingLists1, scaling_list->scaling_lists_8x8,
sizeof (iq_matrix.ucScalingLists1));
memcpy (iq_matrix.ucScalingLists2, scaling_list->scaling_lists_16x16,
sizeof (iq_matrix.ucScalingLists2));
memcpy (iq_matrix.ucScalingLists3, scaling_list->scaling_lists_32x32,
sizeof (iq_matrix.ucScalingLists3));
for (i = 0; i < 6; i++)
iq_matrix.ucScalingListDCCoefSizeID2[i] =
scaling_list->scaling_list_dc_coef_minus8_16x16[i] + 8;
for (i = 0; i < 2; i++)
iq_matrix.ucScalingListDCCoefSizeID3[i] =
scaling_list->scaling_list_dc_coef_minus8_32x32[i] + 8;
GST_TRACE_OBJECT (self, "Getting inverse quantization maxtirx buffer");
if (!gst_d3d11_decoder_get_decoder_buffer (self->d3d11_decoder,
D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX,
&d3d11_buffer_size, &d3d11_buffer)) {
GST_ERROR_OBJECT (self,
"Failed to get decoder buffer for inv. quantization matrix");
return FALSE;
}
memcpy (d3d11_buffer, &iq_matrix, sizeof (iq_matrix));
GST_TRACE_OBJECT (self, "Release inverse quantization maxtirx buffer");
if (!gst_d3d11_decoder_release_decoder_buffer (self->d3d11_decoder,
D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX)) {
GST_ERROR_OBJECT (self, "Failed to release decoder buffer");
return FALSE;
}
} else {
self->submit_iq_data = FALSE;
}
{
guint to_write = slice->nalu.size + 3;