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 | |
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>
-rw-r--r-- | cmdutils.c | 27 | ||||
-rw-r--r-- | cmdutils.h | 24 | ||||
-rw-r--r-- | ffmpeg.c | 4 | ||||
-rw-r--r-- | ffplay.c | 7 | ||||
-rw-r--r-- | libavcodec/avcodec.h | 18 | ||||
-rw-r--r-- | libavcodec/utils.c | 43 |
6 files changed, 63 insertions, 60 deletions
diff --git a/cmdutils.c b/cmdutils.c index c68f37fe20..0679f011b2 100644 --- a/cmdutils.c +++ b/cmdutils.c @@ -749,33 +749,6 @@ int read_file(const char *filename, char **bufptr, size_t *size) return 0; } -void init_pts_correction(PtsCorrectionContext *ctx) -{ - ctx->num_faulty_pts = ctx->num_faulty_dts = 0; - ctx->last_pts = ctx->last_dts = INT64_MIN; -} - -int64_t guess_correct_pts(PtsCorrectionContext *ctx, int64_t reordered_pts, int64_t dts) -{ - int64_t pts = AV_NOPTS_VALUE; - - if (dts != AV_NOPTS_VALUE) { - ctx->num_faulty_dts += dts <= ctx->last_dts; - ctx->last_dts = dts; - } - if (reordered_pts != AV_NOPTS_VALUE) { - ctx->num_faulty_pts += reordered_pts <= ctx->last_pts; - ctx->last_pts = reordered_pts; - } - if ((ctx->num_faulty_pts<=ctx->num_faulty_dts || dts == AV_NOPTS_VALUE) - && reordered_pts != AV_NOPTS_VALUE) - pts = reordered_pts; - else - pts = dts; - - return pts; -} - FILE *get_preset_file(char *filename, size_t filename_size, const char *preset_name, int is_path, const char *codec_name) { diff --git a/cmdutils.h b/cmdutils.h index c3d8a42453..b35b99b2b4 100644 --- a/cmdutils.h +++ b/cmdutils.h @@ -235,30 +235,6 @@ int read_yesno(void); */ int read_file(const char *filename, char **bufptr, size_t *size); -typedef struct { - int64_t num_faulty_pts; /// Number of incorrect PTS values so far - int64_t num_faulty_dts; /// Number of incorrect DTS values so far - int64_t last_pts; /// PTS of the last frame - int64_t last_dts; /// DTS of the last frame -} PtsCorrectionContext; - -/** - * Reset the state of the PtsCorrectionContext. - */ -void init_pts_correction(PtsCorrectionContext *ctx); - -/** - * 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 - * AVCodecContext.reordered_opaque - * @param dts the dts field of the decoded AVPacket - * @return one of the input values, may be AV_NOPTS_VALUE - */ -int64_t guess_correct_pts(PtsCorrectionContext *ctx, int64_t pts, int64_t dts); - /** * Get a file corresponding to a preset file. * @@ -320,7 +320,6 @@ typedef struct AVInputStream { int64_t next_pts; /* synthetic pts for cases where pkt.pts is not defined */ int64_t pts; /* current pts */ - PtsCorrectionContext pts_ctx; int is_start; /* is 1 at the start and after a discontinuity */ int showed_multi_packet_warning; int is_past_recording_time; @@ -1561,7 +1560,7 @@ static int output_packet(AVInputStream *ist, int ist_index, /* no picture yet */ goto discard_packet; } - ist->next_pts = ist->pts = guess_correct_pts(&ist->pts_ctx, picture.pkt_pts, picture.pkt_dts); + ist->next_pts = ist->pts = picture.best_effort_timestamp; if (ist->st->codec->time_base.num != 0) { int ticks= ist->st->parser ? ist->st->parser->repeat_pict+1 : ist->st->codec->ticks_per_frame; ist->next_pts += ((int64_t)AV_TIME_BASE * @@ -2364,7 +2363,6 @@ static int transcode(AVFormatContext **output_files, st= ist->st; ist->pts = st->avg_frame_rate.num ? - st->codec->has_b_frames*AV_TIME_BASE / av_q2d(st->avg_frame_rate) : 0; ist->next_pts = AV_NOPTS_VALUE; - init_pts_correction(&ist->pts_ctx); ist->is_start = 1; } @@ -208,8 +208,6 @@ typedef struct VideoState { char filename[1024]; int width, height, xleft, ytop; - PtsCorrectionContext pts_ctx; - #if CONFIG_AVFILTER AVFilterContext *out_video_filter; ///<the last filter in the video chain #endif @@ -1286,7 +1284,7 @@ retry: if (is->audio_st && is->video_st) av_diff = get_audio_clock(is) - get_video_clock(is); printf("%7.2f A-V:%7.3f s:%3.1f aq=%5dKB vq=%5dKB sq=%5dB f=%"PRId64"/%"PRId64" \r", - get_master_clock(is), av_diff, FFMAX(is->skip_frames-1, 0), aqsize / 1024, vqsize / 1024, sqsize, is->pts_ctx.num_faulty_dts, is->pts_ctx.num_faulty_pts); + get_master_clock(is), av_diff, FFMAX(is->skip_frames-1, 0), aqsize / 1024, vqsize / 1024, sqsize, is->video_st->codec->pts_correction_num_faulty_dts, is->video_st->codec->pts_correction_num_faulty_pts); fflush(stdout); last_time = cur_time; } @@ -1561,7 +1559,6 @@ static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacke is->video_current_pos = -1; SDL_UnlockMutex(is->pictq_mutex); - init_pts_correction(&is->pts_ctx); is->frame_last_pts = AV_NOPTS_VALUE; is->frame_last_delay = 0; is->frame_timer = (double)av_gettime() / 1000000.0; @@ -1576,7 +1573,7 @@ static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacke if (got_picture) { if (decoder_reorder_pts == -1) { - *pts = guess_correct_pts(&is->pts_ctx, frame->pkt_pts, frame->pkt_dts); + *pts = frame->best_effort_timestamp; } else if (decoder_reorder_pts) { *pts = frame->pkt_pts; } else { 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++; |