summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libvdpau/h264_parser.c31
-rw-r--r--src/libvdpau/nal.h29
-rw-r--r--src/libvdpau/vdpau_h264.c10
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) {