diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 8870fded3f..44f45f2330 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2788,6 +2788,7 @@ typedef struct AVCodecParserContext { /* video info */ int pict_type; /* XXX: Put it back in AVCodecContext. */ int repeat_pict; /* XXX: Put it back in AVCodecContext. */ + int parity; int64_t pts; /* pts of the current frame */ int64_t dts; /* dts of the current frame */ diff --git a/libavcodec/mpegvideo_parser.c b/libavcodec/mpegvideo_parser.c index 8beaeb41ab..cc423b7288 100644 --- a/libavcodec/mpegvideo_parser.c +++ b/libavcodec/mpegvideo_parser.c @@ -36,6 +36,7 @@ static void mpegvideo_extract_headers(AVCodecParserContext *s, int horiz_size_ext, vert_size_ext, bit_rate_ext; //FIXME replace the crap with get_bits() s->repeat_pict = 0; + s->parity = 0; buf_end = buf + buf_size; while (buf < buf_end) { start_code= -1; @@ -105,8 +106,11 @@ static void mpegvideo_extract_headers(AVCodecParserContext *s, /* the packet only represents half a frame XXX,FIXME maybe find a different solution */ - if(picture_structure != 3) + if(picture_structure != 3){ s->repeat_pict = -1; + s->parity = picture_structure-1; + }else + s->parity = !top_field_first; } break; } diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 06396eebff..cc09e02776 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -337,8 +337,8 @@ typedef struct AVStream { struct AVCodecParserContext *parser; int64_t cur_dts; - int last_IP_duration; - int64_t last_IP_pts; + int last_IP_duration[2]; + int64_t last_IP_pts[2]; /* av_seek_frame() support */ AVIndexEntry *index_entries; /**< only used if the format does not support seeking natively */ diff --git a/libavformat/utils.c b/libavformat/utils.c index 79d502cd9e..4936349d7d 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -702,21 +702,30 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, /* interpolate PTS and DTS if they are not present */ if(delay <=1){ if (presentation_delayed) { + int fields= 2 + (pc ? pc->repeat_pict : 0); + int field_duration= pkt->duration / fields; + int parity= pc ? pc->parity : 0; /* DTS = decompression timestamp */ /* PTS = presentation timestamp */ if (pkt->dts == AV_NOPTS_VALUE) - pkt->dts = st->last_IP_pts; + pkt->dts = st->last_IP_pts[parity]; update_initial_timestamps(s, pkt->stream_index, pkt->dts, pkt->pts); if (pkt->dts == AV_NOPTS_VALUE) pkt->dts = st->cur_dts; /* this is tricky: the dts must be incremented by the duration of the frame we are displaying, i.e. the last I- or P-frame */ - if (st->last_IP_duration == 0) - st->last_IP_duration = pkt->duration; - st->cur_dts = pkt->dts + st->last_IP_duration; - st->last_IP_duration = pkt->duration; - st->last_IP_pts= pkt->pts; + st->cur_dts = pkt->dts; + for(i=0; ilast_IP_duration[p]) + st->last_IP_duration[p]= field_duration; + st->cur_dts += st->last_IP_duration[p]; + st->last_IP_pts[p]= pkt->pts; + if(pkt->pts != AV_NOPTS_VALUE) + st->last_IP_pts[p] += i*field_duration; + st->last_IP_duration[p]= field_duration; + } /* cannot compute PTS if not present (we can compute it only by knowing the future */ } else if(pkt->pts != AV_NOPTS_VALUE || pkt->dts != AV_NOPTS_VALUE || pkt->duration){ @@ -1014,7 +1023,8 @@ static void av_read_frame_flush(AVFormatContext *s) av_parser_close(st->parser); st->parser = NULL; } - st->last_IP_pts = AV_NOPTS_VALUE; + st->last_IP_pts[0] = + st->last_IP_pts[1] = AV_NOPTS_VALUE; st->cur_dts = AV_NOPTS_VALUE; /* we set the current DTS to an unspecified origin */ } } @@ -1622,7 +1632,8 @@ static void av_estimate_timings_from_pts(AVFormatContext *ic, offset_t old_offse for(i=0; inb_streams; i++){ st= ic->streams[i]; st->cur_dts= st->first_dts; - st->last_IP_pts = AV_NOPTS_VALUE; + st->last_IP_pts[0] = + st->last_IP_pts[1] = AV_NOPTS_VALUE; } } @@ -2181,7 +2192,8 @@ AVStream *av_new_stream(AVFormatContext *s, int id) /* default pts setting is MPEG-like */ av_set_pts_info(st, 33, 1, 90000); - st->last_IP_pts = AV_NOPTS_VALUE; + st->last_IP_pts[0] = + st->last_IP_pts[1] = AV_NOPTS_VALUE; for(i=0; ipts_buffer[i]= AV_NOPTS_VALUE;