diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 9fd2fb31ff..596f8efebc 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -37,8 +37,8 @@ extern "C" { #define AV_STRINGIFY(s) AV_TOSTRING(s) #define AV_TOSTRING(s) #s -#define LIBAVCODEC_VERSION_INT ((51<<16)+(40<<8)+2) -#define LIBAVCODEC_VERSION 51.40.2 +#define LIBAVCODEC_VERSION_INT ((51<<16)+(40<<8)+3) +#define LIBAVCODEC_VERSION 51.40.3 #define LIBAVCODEC_BUILD LIBAVCODEC_VERSION_INT #define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION) @@ -2940,6 +2940,9 @@ typedef struct AVCodecParserContext { int flags; #define PARSER_FLAG_COMPLETE_FRAMES 0x0001 + + int64_t offset; ///< byte offset from starting packet start + int64_t last_offset; } AVCodecParserContext; typedef struct AVCodecParser { diff --git a/libavcodec/parser.c b/libavcodec/parser.c index d5b1bf1689..1c21d50fe5 100644 --- a/libavcodec/parser.c +++ b/libavcodec/parser.c @@ -124,6 +124,7 @@ int av_parser_parse(AVCodecParserContext *s, s->fetch_timestamp=0; s->last_pts = pts; s->last_dts = dts; + s->last_offset = 0; s->cur_frame_pts[k] = s->cur_frame_dts[k] = AV_NOPTS_VALUE; } @@ -138,6 +139,7 @@ int av_parser_parse(AVCodecParserContext *s, s->frame_offset = s->last_frame_offset; s->pts = s->last_pts; s->dts = s->last_dts; + s->offset = s->last_offset; /* offset of the next frame */ s->last_frame_offset = s->cur_offset + index; @@ -156,6 +158,7 @@ int av_parser_parse(AVCodecParserContext *s, s->last_pts = s->cur_frame_pts[k]; s->last_dts = s->cur_frame_dts[k]; + s->last_offset = s->last_frame_offset - s->cur_frame_offset[k]; /* some parsers tell us the packet size even before seeing the first byte of the next packet, so the next pts/dts is in the next chunk */ diff --git a/libavformat/avformat.h b/libavformat/avformat.h index c5d5df0197..d6525954bb 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -25,8 +25,8 @@ extern "C" { #endif -#define LIBAVFORMAT_VERSION_INT ((51<<16)+(12<<8)+0) -#define LIBAVFORMAT_VERSION 51.12.0 +#define LIBAVFORMAT_VERSION_INT ((51<<16)+(12<<8)+1) +#define LIBAVFORMAT_VERSION 51.12.1 #define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT #define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION) @@ -309,7 +309,8 @@ typedef struct AVStream { char language[4]; /** ISO 639 3-letter language code (empty string if undefined) */ /* av_read_frame() support */ - int need_parsing; ///< 1->full parsing needed, 2->only parse headers dont repack +#define AVSTREAM_PARSE_TIMESTAMPS 3 /**< full parsing and interpolation of timestamps for frames not starting on packet boundary */ + int need_parsing; ///< 1->full parsing needed, 2->only parse headers dont repack, 3->full parsing and interpolate timestamps struct AVCodecParserContext *parser; int64_t cur_dts; diff --git a/libavformat/avidec.c b/libavformat/avidec.c index 02078bc77b..d434c57181 100644 --- a/libavformat/avidec.c +++ b/libavformat/avidec.c @@ -452,8 +452,8 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) if (size%2) /* 2-aligned (fix for Stargate SG-1 - 3x18 - Shades of Grey.avi) */ url_fskip(pb, 1); /* Force parsing as several audio frames can be in - * one packet. */ - st->need_parsing = 1; + * one packet and timestamps refer to packet start*/ + st->need_parsing = AVSTREAM_PARSE_TIMESTAMPS; /* ADTS header is in extradata, AAC without header must be stored as exact frames, parser not needed and it will fail */ if (st->codec->codec_id == CODEC_ID_AAC && st->codec->extradata_size) st->need_parsing = 0; diff --git a/libavformat/utils.c b/libavformat/utils.c index c82d7dac84..b748b546ca 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -584,6 +584,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, AVCodecParserContext *pc, AVPacket *pkt) { int num, den, presentation_delayed, delay, i; + int64_t offset; /* handle wrapping */ if(st->cur_dts != AV_NOPTS_VALUE){ if(pkt->pts != AV_NOPTS_VALUE) @@ -599,6 +600,16 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, } } + /* correct timestamps with byte offset if demuxers only have timestamps on packet boundaries */ + if(pc && st->need_parsing == AVSTREAM_PARSE_TIMESTAMPS && pkt->size){ + /* this will estimate bitrate based on this frame's duration and size */ + offset = av_rescale(pc->offset, pkt->duration, pkt->size); + if(pkt->pts != AV_NOPTS_VALUE) + pkt->pts += offset; + if(pkt->dts != AV_NOPTS_VALUE) + pkt->dts += offset; + } + if(is_intra_only(st->codec)) pkt->flags |= PKT_FLAG_KEY;