From 415d5df7ee716fc5d8b652b359dc16187ab0e905 Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Thu, 13 Nov 2014 15:00:21 +0100 Subject: [PATCH] decoder: h264: fix detection of top-field-first (TFF) flag. Use the SEI pic_timing() message to track the pic_struct variable when present, or infer it from the regular slice header flags field_pic_flag and bottom_field_flag. This fixes temporal sequence ordering when the output pictures are to be displayed. https://bugzilla.gnome.org/show_bug.cgi?id=739291 --- gst-libs/gst/vaapi/gstvaapidecoder_h264.c | 65 ++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 9 deletions(-) diff --git a/gst-libs/gst/vaapi/gstvaapidecoder_h264.c b/gst-libs/gst/vaapi/gstvaapidecoder_h264.c index 6b57fa6..ac1e835 100644 --- a/gst-libs/gst/vaapi/gstvaapidecoder_h264.c +++ b/gst-libs/gst/vaapi/gstvaapidecoder_h264.c @@ -369,7 +369,9 @@ gst_vaapi_frame_store_split_fields(GstVaapiFrameStore *fs) g_return_val_if_fail(fs->num_buffers == 1, FALSE); - first_field->base.structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD; + first_field->base.structure = GST_VAAPI_PICTURE_IS_TFF(first_field) ? + GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD : + GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD; GST_VAAPI_PICTURE_FLAG_SET(first_field, GST_VAAPI_PICTURE_FLAG_INTERLACED); second_field = gst_vaapi_picture_h264_new_field(first_field); @@ -490,6 +492,7 @@ struct _GstVaapiDecoderH264Private { guint nal_length_size; guint mb_width; guint mb_height; + guint pic_structure; // pic_struct (from SEI pic_timing() or inferred) gint32 field_poc[2]; // 0:TopFieldOrderCnt / 1:BottomFieldOrderCnt gint32 poc_msb; // PicOrderCntMsb gint32 poc_lsb; // pic_order_cnt_lsb (from slice_header()) @@ -1490,6 +1493,7 @@ decode_current_picture(GstVaapiDecoderH264 *decoder) if (!is_valid_state(priv->decoder_state, GST_H264_VIDEO_STATE_VALID_PICTURE)) goto drop_frame; priv->decoder_state = 0; + priv->pic_structure = GST_H264_SEI_PIC_STRUCT_FRAME; if (!picture) return GST_VAAPI_DECODER_STATUS_SUCCESS; @@ -1510,6 +1514,7 @@ error: drop_frame: priv->decoder_state = 0; + priv->pic_structure = GST_H264_SEI_PIC_STRUCT_FRAME; return GST_VAAPI_DECODER_STATUS_DROP_FRAME; } @@ -1706,6 +1711,34 @@ decode_pps(GstVaapiDecoderH264 *decoder, GstVaapiDecoderUnit *unit) } static GstVaapiDecoderStatus +decode_sei(GstVaapiDecoderH264 *decoder, GstVaapiDecoderUnit *unit) +{ + GstVaapiDecoderH264Private * const priv = &decoder->priv; + GstVaapiParserInfoH264 * const pi = unit->parsed_info; + guint i; + + GST_DEBUG("decode SEI messages"); + + for (i = 0; i < pi->data.sei->len; i++) { + const GstH264SEIMessage * const sei = + &g_array_index(pi->data.sei, GstH264SEIMessage, i); + + switch (sei->payloadType) { + case GST_H264_SEI_PIC_TIMING: { + const GstH264PicTiming * const pic_timing = + &sei->payload.pic_timing; + if (pic_timing->pic_struct_present_flag) + priv->pic_structure = pic_timing->pic_struct; + break; + } + default: + break; + } + } + return GST_VAAPI_DECODER_STATUS_SUCCESS; +} + +static GstVaapiDecoderStatus decode_sequence_end(GstVaapiDecoderH264 *decoder) { GstVaapiDecoderH264Private * const priv = &decoder->priv; @@ -2881,14 +2914,28 @@ init_picture( } /* Initialize picture structure */ - if (!slice_hdr->field_pic_flag) - base_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME; - else { + if (slice_hdr->field_pic_flag) { GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_INTERLACED); - if (!slice_hdr->bottom_field_flag) - base_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD; - else - base_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD; + priv->pic_structure = slice_hdr->bottom_field_flag ? + GST_H264_SEI_PIC_STRUCT_BOTTOM_FIELD : + GST_H264_SEI_PIC_STRUCT_TOP_FIELD; + } + + base_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_FRAME; + switch (priv->pic_structure) { + case GST_H264_SEI_PIC_STRUCT_TOP_FIELD: + base_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD; + if (GST_VAAPI_PICTURE_IS_FIRST_FIELD(picture)) + GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_TFF); + break; + case GST_H264_SEI_PIC_STRUCT_BOTTOM_FIELD: + base_picture->structure = GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD; + break; + case GST_H264_SEI_PIC_STRUCT_TOP_BOTTOM_TOP: + case GST_H264_SEI_PIC_STRUCT_TOP_BOTTOM: + if (GST_VAAPI_PICTURE_IS_FIRST_FIELD(picture)) + GST_VAAPI_PICTURE_FLAG_SET(picture, GST_VAAPI_PICTURE_FLAG_TFF); + break; } picture->structure = base_picture->structure; @@ -3781,7 +3828,7 @@ decode_unit(GstVaapiDecoderH264 *decoder, GstVaapiDecoderUnit *unit) status = decode_sequence_end(decoder); break; case GST_H264_NAL_SEI: - status = GST_VAAPI_DECODER_STATUS_SUCCESS; + status = decode_sei(decoder, unit); break; default: GST_WARNING("unsupported NAL unit type %d", pi->nalu.type); -- 2.7.4