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)
{
*/
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.
*
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;
/* 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 *
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;
}
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
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;
}
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;
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 {
* - 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
* - 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;
/**
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;
}
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) {
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,
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++;