mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-08 13:22:53 +02:00
Implement guessed_pts in avcodec_decode_video2
Signed-off-by: Nicolas George <nicolas.george@normalesup.org> Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
parent
52b2e95cd9
commit
76ad67cae7
27
cmdutils.c
27
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)
|
||||
{
|
||||
|
24
cmdutils.h
24
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.
|
||||
*
|
||||
|
4
ffmpeg.c
4
ffmpeg.c
@ -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;
|
||||
}
|
||||
|
||||
|
7
ffplay.c
7
ffplay.c
@ -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 {
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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++;
|
||||
|
Loading…
Reference in New Issue
Block a user