diff options
author | Nicolas George <nicolas.george@normalesup.org> | 2011-01-30 20:18:31 +0100 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2011-02-07 19:32:07 +0100 |
commit | 76ad67cae751658ce2d84e83b38a4d673e9e85a3 (patch) | |
tree | fd7a80906aa640e700f427539a9c87dd2d27b5c0 /libavcodec | |
parent | 52b2e95cd9f829b83b879a0694173d4ef1558c46 (diff) | |
download | ffmpeg-76ad67cae751658ce2d84e83b38a4d673e9e85a3.tar.gz |
Implement guessed_pts in avcodec_decode_video2
Signed-off-by: Nicolas George <nicolas.george@normalesup.org>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/avcodec.h | 18 | ||||
-rw-r--r-- | libavcodec/utils.c | 43 |
2 files changed, 60 insertions, 1 deletions
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index dbfb77795d..f96ae84740 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1026,6 +1026,13 @@ typedef struct AVPanScan{ * - decoding: Read by user.\ */\ int64_t pkt_dts;\ +\ + /**\ + * frame timestamp estimated using various heuristics, in stream time base\ + * - encoding: unused\ + * - decoding: set by libavcodec, read by user.\ + */\ + int64_t best_effort_timestamp;\ #define FF_QSCALE_TYPE_MPEG1 0 @@ -2825,6 +2832,17 @@ typedef struct AVCodecContext { * - encoding: unused */ AVPacket *pkt; + + /** + * Current statistics for PTS correction. + * - decoding: maintained and used by libavcodec + * - encoding: unused + */ + int64_t pts_correction_num_faulty_pts; /// Number of incorrect PTS values so far + int64_t pts_correction_num_faulty_dts; /// Number of incorrect DTS values so far + int64_t pts_correction_last_pts; /// PTS of the last frame + int64_t pts_correction_last_dts; /// DTS of the last frame + } AVCodecContext; /** diff --git a/libavcodec/utils.c b/libavcodec/utils.c index e9db33e9d7..2a95975273 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -448,7 +448,7 @@ enum PixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum void avcodec_get_frame_defaults(AVFrame *pic){ memset(pic, 0, sizeof(AVFrame)); - pic->pts= AV_NOPTS_VALUE; + pic->pts = pic->best_effort_timestamp = AV_NOPTS_VALUE; pic->key_frame= 1; } @@ -538,6 +538,11 @@ int attribute_align_arg avcodec_open(AVCodecContext *avctx, AVCodec *codec) goto free_and_end; } + avctx->pts_correction_num_faulty_pts = + avctx->pts_correction_num_faulty_dts = 0; + avctx->pts_correction_last_pts = + avctx->pts_correction_last_dts = INT64_MIN; + if(avctx->codec->init){ ret = avctx->codec->init(avctx); if (ret < 0) { @@ -608,6 +613,39 @@ int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, return ret; } +/** + * Attempt to guess proper monotonic timestamps for decoded video frames + * which might have incorrect times. Input timestamps may wrap around, in + * which case the output will as well. + * + * @param pts the pts field of the decoded AVPacket, as passed through + * AVFrame.pkt_pts + * @param dts the dts field of the decoded AVPacket + * @return one of the input values, may be AV_NOPTS_VALUE + */ +static int64_t guess_correct_pts(AVCodecContext *ctx, + int64_t reordered_pts, int64_t dts) +{ + int64_t pts = AV_NOPTS_VALUE; + + if (dts != AV_NOPTS_VALUE) { + ctx->pts_correction_num_faulty_dts += dts <= ctx->pts_correction_last_dts; + ctx->pts_correction_last_dts = dts; + } + if (reordered_pts != AV_NOPTS_VALUE) { + ctx->pts_correction_num_faulty_pts += reordered_pts <= ctx->pts_correction_last_pts; + ctx->pts_correction_last_pts = reordered_pts; + } + if ((ctx->pts_correction_num_faulty_pts<=ctx->pts_correction_num_faulty_dts || dts == AV_NOPTS_VALUE) + && reordered_pts != AV_NOPTS_VALUE) + pts = reordered_pts; + else + pts = dts; + + return pts; +} + + #if FF_API_VIDEO_OLD int attribute_align_arg avcodec_decode_video(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, @@ -643,6 +681,9 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi emms_c(); //needed to avoid an emms_c() call before every return; picture->pkt_dts= avpkt->dts; + picture->best_effort_timestamp = guess_correct_pts(avctx, + picture->pkt_pts, + picture->pkt_dts); if (*got_picture_ptr) avctx->frame_number++; |