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;
|
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,
|
FILE *get_preset_file(char *filename, size_t filename_size,
|
||||||
const char *preset_name, int is_path, const char *codec_name)
|
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);
|
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.
|
* 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
|
int64_t next_pts; /* synthetic pts for cases where pkt.pts
|
||||||
is not defined */
|
is not defined */
|
||||||
int64_t pts; /* current pts */
|
int64_t pts; /* current pts */
|
||||||
PtsCorrectionContext pts_ctx;
|
|
||||||
int is_start; /* is 1 at the start and after a discontinuity */
|
int is_start; /* is 1 at the start and after a discontinuity */
|
||||||
int showed_multi_packet_warning;
|
int showed_multi_packet_warning;
|
||||||
int is_past_recording_time;
|
int is_past_recording_time;
|
||||||
@ -1561,7 +1560,7 @@ static int output_packet(AVInputStream *ist, int ist_index,
|
|||||||
/* no picture yet */
|
/* no picture yet */
|
||||||
goto discard_packet;
|
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) {
|
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;
|
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 *
|
ist->next_pts += ((int64_t)AV_TIME_BASE *
|
||||||
@ -2364,7 +2363,6 @@ static int transcode(AVFormatContext **output_files,
|
|||||||
st= ist->st;
|
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->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;
|
ist->next_pts = AV_NOPTS_VALUE;
|
||||||
init_pts_correction(&ist->pts_ctx);
|
|
||||||
ist->is_start = 1;
|
ist->is_start = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
7
ffplay.c
7
ffplay.c
@ -208,8 +208,6 @@ typedef struct VideoState {
|
|||||||
char filename[1024];
|
char filename[1024];
|
||||||
int width, height, xleft, ytop;
|
int width, height, xleft, ytop;
|
||||||
|
|
||||||
PtsCorrectionContext pts_ctx;
|
|
||||||
|
|
||||||
#if CONFIG_AVFILTER
|
#if CONFIG_AVFILTER
|
||||||
AVFilterContext *out_video_filter; ///<the last filter in the video chain
|
AVFilterContext *out_video_filter; ///<the last filter in the video chain
|
||||||
#endif
|
#endif
|
||||||
@ -1286,7 +1284,7 @@ retry:
|
|||||||
if (is->audio_st && is->video_st)
|
if (is->audio_st && is->video_st)
|
||||||
av_diff = get_audio_clock(is) - get_video_clock(is);
|
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",
|
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);
|
fflush(stdout);
|
||||||
last_time = cur_time;
|
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;
|
is->video_current_pos = -1;
|
||||||
SDL_UnlockMutex(is->pictq_mutex);
|
SDL_UnlockMutex(is->pictq_mutex);
|
||||||
|
|
||||||
init_pts_correction(&is->pts_ctx);
|
|
||||||
is->frame_last_pts = AV_NOPTS_VALUE;
|
is->frame_last_pts = AV_NOPTS_VALUE;
|
||||||
is->frame_last_delay = 0;
|
is->frame_last_delay = 0;
|
||||||
is->frame_timer = (double)av_gettime() / 1000000.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 (got_picture) {
|
||||||
if (decoder_reorder_pts == -1) {
|
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) {
|
} else if (decoder_reorder_pts) {
|
||||||
*pts = frame->pkt_pts;
|
*pts = frame->pkt_pts;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1026,6 +1026,13 @@ typedef struct AVPanScan{
|
|||||||
* - decoding: Read by user.\
|
* - decoding: Read by user.\
|
||||||
*/\
|
*/\
|
||||||
int64_t pkt_dts;\
|
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
|
#define FF_QSCALE_TYPE_MPEG1 0
|
||||||
@ -2825,6 +2832,17 @@ typedef struct AVCodecContext {
|
|||||||
* - encoding: unused
|
* - encoding: unused
|
||||||
*/
|
*/
|
||||||
AVPacket *pkt;
|
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;
|
} AVCodecContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -448,7 +448,7 @@ enum PixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum
|
|||||||
void avcodec_get_frame_defaults(AVFrame *pic){
|
void avcodec_get_frame_defaults(AVFrame *pic){
|
||||||
memset(pic, 0, sizeof(AVFrame));
|
memset(pic, 0, sizeof(AVFrame));
|
||||||
|
|
||||||
pic->pts= AV_NOPTS_VALUE;
|
pic->pts = pic->best_effort_timestamp = AV_NOPTS_VALUE;
|
||||||
pic->key_frame= 1;
|
pic->key_frame= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -538,6 +538,11 @@ int attribute_align_arg avcodec_open(AVCodecContext *avctx, AVCodec *codec)
|
|||||||
goto free_and_end;
|
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){
|
if(avctx->codec->init){
|
||||||
ret = avctx->codec->init(avctx);
|
ret = avctx->codec->init(avctx);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@ -608,6 +613,39 @@ int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size,
|
|||||||
return ret;
|
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
|
#if FF_API_VIDEO_OLD
|
||||||
int attribute_align_arg avcodec_decode_video(AVCodecContext *avctx, AVFrame *picture,
|
int attribute_align_arg avcodec_decode_video(AVCodecContext *avctx, AVFrame *picture,
|
||||||
int *got_picture_ptr,
|
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;
|
emms_c(); //needed to avoid an emms_c() call before every return;
|
||||||
|
|
||||||
picture->pkt_dts= avpkt->dts;
|
picture->pkt_dts= avpkt->dts;
|
||||||
|
picture->best_effort_timestamp = guess_correct_pts(avctx,
|
||||||
|
picture->pkt_pts,
|
||||||
|
picture->pkt_dts);
|
||||||
|
|
||||||
if (*got_picture_ptr)
|
if (*got_picture_ptr)
|
||||||
avctx->frame_number++;
|
avctx->frame_number++;
|
||||||
|
Loading…
Reference in New Issue
Block a user