Skip to content
Snippets Groups Projects

codecs: h264decoder: Add support for interlaced stream

Merged Seungha Yang requested to merge seungha.yang/gst-plugins-bad:h264-interlaced into master
1 file
+ 87
13
Compare changes
  • Side-by-side
  • Inline
+ 87
13
@@ -152,6 +152,8 @@ static gboolean gst_d3d11_h264_dec_new_sequence (GstH264Decoder * decoder,
const GstH264SPS * sps, gint max_dpb_size);
static gboolean gst_d3d11_h264_dec_new_picture (GstH264Decoder * decoder,
GstVideoCodecFrame * frame, GstH264Picture * picture);
static GstH264Picture *gst_d3d11_h264_dec_duplicate_picture (GstH264Decoder *
decoder, GstH264Picture * picture);
static GstFlowReturn gst_d3d11_h264_dec_output_picture (GstH264Decoder *
decoder, GstVideoCodecFrame * frame, GstH264Picture * picture);
static gboolean gst_d3d11_h264_dec_start_picture (GstH264Decoder * decoder,
@@ -227,6 +229,8 @@ gst_d3d11_h264_dec_class_init (GstD3D11H264DecClass * klass, gpointer data)
GST_DEBUG_FUNCPTR (gst_d3d11_h264_dec_new_sequence);
h264decoder_class->new_picture =
GST_DEBUG_FUNCPTR (gst_d3d11_h264_dec_new_picture);
h264decoder_class->duplicate_picture =
GST_DEBUG_FUNCPTR (gst_d3d11_h264_dec_duplicate_picture);
h264decoder_class->output_picture =
GST_DEBUG_FUNCPTR (gst_d3d11_h264_dec_output_picture);
h264decoder_class->start_picture =
@@ -560,7 +564,6 @@ gst_d3d11_h264_dec_start_picture (GstH264Decoder * decoder,
dpb_array = gst_h264_dpb_get_pictures_all (dpb);
for (i = 0; i < dpb_array->len; i++) {
guint ref = 3;
GstH264Picture *other = g_array_index (dpb_array, GstH264Picture *, i);
ID3D11VideoDecoderOutputView *other_view;
gint id = 0xff;
@@ -568,19 +571,59 @@ gst_d3d11_h264_dec_start_picture (GstH264Decoder * decoder,
if (!GST_H264_PICTURE_IS_REF (other))
continue;
/* The second field picture will be handled differently */
if (other->second_field)
continue;
other_view = gst_d3d11_h264_dec_get_output_view_from_picture (self, other);
if (other_view)
id = gst_d3d11_decoder_get_output_view_index (other_view);
self->ref_frame_list[i].Index7Bits = id;
self->ref_frame_list[i].AssociatedFlag =
GST_H264_PICTURE_IS_LONG_TERM_REF (other);
self->field_order_cnt_list[i][0] = other->top_field_order_cnt;
self->field_order_cnt_list[i][1] = other->bottom_field_order_cnt;
self->frame_num_list[i] = self->ref_frame_list[i].AssociatedFlag
? other->long_term_pic_num : other->frame_num;
self->used_for_reference_flags |= ref << (2 * i);
if (GST_H264_PICTURE_IS_LONG_TERM_REF (other)) {
self->ref_frame_list[i].AssociatedFlag = 1;
self->frame_num_list[i] = other->long_term_pic_num;
} else {
self->ref_frame_list[i].AssociatedFlag = 0;
self->frame_num_list[i] = other->frame_num;
}
switch (other->field) {
case GST_H264_PICTURE_FIELD_TOP_FIELD:
self->field_order_cnt_list[i][0] = other->top_field_order_cnt;
self->used_for_reference_flags |= 0x1 << (2 * i);
break;
case GST_H264_PICTURE_FIELD_BOTTOM_FIELD:
self->field_order_cnt_list[i][1] = other->bottom_field_order_cnt;
self->used_for_reference_flags |= 0x1 << (2 * i + 1);
break;
default:
self->field_order_cnt_list[i][0] = other->top_field_order_cnt;
self->field_order_cnt_list[i][1] = other->bottom_field_order_cnt;
self->used_for_reference_flags |= 0x3 << (2 * i);
break;
}
if (other->other_field && other->other_field != picture) {
GstH264Picture *other_field = other->other_field;
switch (other_field->field) {
case GST_H264_PICTURE_FIELD_TOP_FIELD:
self->field_order_cnt_list[i][0] = other_field->top_field_order_cnt;
self->used_for_reference_flags |= 0x1 << (2 * i);
break;
case GST_H264_PICTURE_FIELD_BOTTOM_FIELD:
self->field_order_cnt_list[i][1] =
other_field->bottom_field_order_cnt;
self->used_for_reference_flags |= 0x1 << (2 * i + 1);
break;
default:
break;
}
}
self->non_existing_frame_flags |= (other->nonexisting) << i;
}
@@ -591,12 +634,12 @@ gst_d3d11_h264_dec_start_picture (GstH264Decoder * decoder,
pic_params.RefPicFlag = GST_H264_PICTURE_IS_REF (picture);
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) {
if (picture->field == GST_H264_PICTURE_FIELD_TOP_FIELD) {
pic_params.CurrFieldOrderCnt[0] = picture->top_field_order_cnt;
pic_params.CurrFieldOrderCnt[1] = 0;
} else if (picture->field == GST_H264_PICTURE_FIELD_BOTTOM_FIELD) {
pic_params.CurrFieldOrderCnt[0] = 0;
pic_params.CurrFieldOrderCnt[1] = picture->bottom_field_order_cnt;
} else {
pic_params.CurrFieldOrderCnt[0] = picture->top_field_order_cnt;
pic_params.CurrFieldOrderCnt[1] = picture->bottom_field_order_cnt;
@@ -707,6 +750,35 @@ gst_d3d11_h264_dec_new_picture (GstH264Decoder * decoder,
return TRUE;
}
static GstH264Picture *
gst_d3d11_h264_dec_duplicate_picture (GstH264Decoder * decoder,
GstH264Picture * picture)
{
GstD3D11H264Dec *self = GST_D3D11_H264_DEC (decoder);
GstBuffer *view_buffer;
GstD3D11Memory *mem;
GstH264Picture *new_picture;
view_buffer = gst_h264_picture_get_user_data (picture);
if (!view_buffer) {
GST_ERROR_OBJECT (self, "Parent picture does not have output view buffer");
return NULL;
}
new_picture = gst_h264_picture_new ();
mem = (GstD3D11Memory *) gst_buffer_peek_memory (view_buffer, 0);
GST_LOG_OBJECT (self, "Duplicate output with buffer %" GST_PTR_FORMAT
" (index %d)", view_buffer, mem->subresource_index);
gst_h264_picture_set_user_data (new_picture,
gst_buffer_ref (view_buffer), (GDestroyNotify) gst_buffer_unref);
return new_picture;
}
static GstFlowReturn
gst_d3d11_h264_dec_output_picture (GstH264Decoder * decoder,
GstVideoCodecFrame * frame, GstH264Picture * picture)
@@ -903,7 +975,9 @@ gst_d3d11_h264_dec_picture_params_from_sps (GstD3D11H264Dec * self,
(params)->f = (sps)->f
params->wFrameWidthInMbsMinus1 = sps->pic_width_in_mbs_minus1;
params->wFrameHeightInMbsMinus1 = sps->pic_height_in_map_units_minus1;
params->wFrameHeightInMbsMinus1 =
((sps->pic_height_in_map_units_minus1 + 1) << !sps->frame_mbs_only_flag)
- 1;
params->residual_colour_transform_flag = sps->separate_colour_plane_flag;
params->MbaffFrameFlag = sps->mb_adaptive_frame_field_flag && field_pic;
params->field_pic_flag = field_pic;
Loading