diff options
-rw-r--r-- | src/libvdpau/h264_parser.c | 31 | ||||
-rw-r--r-- | src/libvdpau/nal.h | 29 | ||||
-rw-r--r-- | src/libvdpau/vdpau_h264.c | 10 |
3 files changed, 68 insertions, 2 deletions
diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index bb2bad31e..fdc48f043 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -246,6 +246,7 @@ int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser) } break; case NAL_SEI: + memset(&(nal->sei), 0x00, sizeof(struct sei_message)); parse_sei(buf, parser); ret = nal->nal_unit_type; break; @@ -470,6 +471,7 @@ uint8_t parse_sps(struct buf_reader *buf, struct nal_parser *parser) void parse_sei(struct buf_reader *buf, struct nal_parser *parser) { struct sei_message *sei = &(parser->current_nal->sei); + struct seq_parameter_set_rbsp *sps = parser->current_nal->sps; uint8_t tmp; sei->payload_type = 0; @@ -492,6 +494,35 @@ void parse_sei(struct buf_reader *buf, struct nal_parser *parser) sei->pic_timing.cpb_removal_delay = read_bits(buf, 5); sei->pic_timing.dpb_output_delay = read_bits(buf, 5); } + + if(sps && sps->vui_parameters_present_flag && + sps->vui_parameters.pic_struct_present_flag) { + sei->pic_timing.pic_struct = read_bits(buf, 4); + switch(sei->pic_timing.pic_struct) { + case DISP_FRAME: + parser->current_nal->interlaced = 0; + parser->current_nal->repeat_pic = 0; + break; + case DISP_TOP: + case DISP_BOTTOM: + case DISP_TOP_BOTTOM: + case DISP_BOTTOM_TOP: + parser->current_nal->interlaced = 1; + break; + case DISP_TOP_BOTTOM_TOP: + case DISP_BOTTOM_TOP_BOTTOM: + parser->current_nal->interlaced = 1; + parser->current_nal->repeat_pic = 1; + break; + case DISP_FRAME_DOUBLING: + parser->current_nal->interlaced = 0; + parser->current_nal->repeat_pic = 2; + break; + case DISP_FRAME_TRIPLING: + parser->current_nal->interlaced = 0; + parser->current_nal->repeat_pic = 3; + } + } } } diff --git a/src/libvdpau/nal.h b/src/libvdpau/nal.h index 40e463716..2fbbeff97 100644 --- a/src/libvdpau/nal.h +++ b/src/libvdpau/nal.h @@ -43,6 +43,19 @@ enum nal_unit_types NAL_SPS_EXT }; +enum pic_struct { + DISP_FRAME = 0, + DISP_TOP, + DISP_BOTTOM, + DISP_TOP_BOTTOM, + DISP_BOTTOM_TOP, + DISP_TOP_BOTTOM_TOP, + DISP_TOP_TOP_BOTTOM, + DISP_BOTTOM_TOP_BOTTOM, + DISP_FRAME_DOUBLING, + DISP_FRAME_TRIPLING +}; + /* slice types repeat from 5-9, we * need a helper function for comparison */ @@ -274,6 +287,16 @@ struct pic_parameter_set_rbsp int32_t second_chroma_qp_index_offset; }; +/*struct clock_timestamp { + uint8_t ct_type; + uint8_t nuit_fiel_based_flag; + uint8_t counting_type; + uint8_t full_timestamp_flag; + uint8_t discontinuity_flag; + uint8_t cnt_dropped_flag; + uint8_t n_frames +};*/ + /* sei contains several additional info, we do * only care for pic_timing, to handle display * reordering @@ -291,7 +314,8 @@ struct sei_message uint8_t cpb_removal_delay; uint8_t dpb_output_delay; - /* ignore the rest */ + uint8_t pic_struct; + //uint8_t clock_timestamp_flag[3]; } pic_timing; }; @@ -397,6 +421,9 @@ struct nal_unit uint32_t top_field_order_cnt; uint32_t bottom_field_order_cnt; + uint8_t interlaced; + uint8_t repeat_pic; + struct sei_message sei; struct seq_parameter_set_rbsp *sps; diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 46923b557..0f6639125 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -475,11 +475,19 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, else { img->bad_frame = 0; - if(!pic.field_pic_flag && !pic.mb_adaptive_frame_field_flag) + if((sps->vui_parameters_present_flag && + sps->vui_parameters.pic_struct_present_flag && + !this->nal_parser->current_nal->interlaced) || + !pic.field_pic_flag && !pic.mb_adaptive_frame_field_flag) img->progressive_frame = 1; else img->progressive_frame = 0; + if(!img->progressive_frame && this->nal_parser->current_nal->repeat_pic) + img->repeat_first_field = 1; + else if(img->progressive_frame && this->nal_parser->current_nal->repeat_pic) + img->duration *= this->nal_parser->current_nal->repeat_pic; + struct decoded_picture *decoded_pic = NULL; if(pic.is_reference) { if(!slc->field_pic_flag || !this->wait_for_bottom_field) { |