[FFmpeg-cvslog] Implement guessed_pts in avcodec_decode_video2

Nicolas George git
Mon Feb 7 21:15:26 CET 2011


ffmpeg | branch: master | Nicolas George <nicolas.george at normalesup.org> | Sun Jan 30 20:18:31 2011 +0100| [76ad67cae751658ce2d84e83b38a4d673e9e85a3] | committer: Michael Niedermayer

Implement guessed_pts in avcodec_decode_video2

Signed-off-by: Nicolas George <nicolas.george at normalesup.org>
Signed-off-by: Michael Niedermayer <michaelni at gmx.at>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=76ad67cae751658ce2d84e83b38a4d673e9e85a3
---

 cmdutils.c           |   27 ---------------------------
 cmdutils.h           |   24 ------------------------
 ffmpeg.c             |    4 +---
 ffplay.c             |    7 ++-----
 libavcodec/avcodec.h |   18 ++++++++++++++++++
 libavcodec/utils.c   |   43 ++++++++++++++++++++++++++++++++++++++++++-
 6 files changed, 63 insertions(+), 60 deletions(-)

diff --git a/cmdutils.c b/cmdutils.c
index c68f37f..0679f01 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 c3d8a42..b35b99b 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.
  *
diff --git a/ffmpeg.c b/ffmpeg.c
index dfd9f9a..379ac04 100644
--- a/ffmpeg.c
+++ b/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;
     }
 
diff --git a/ffplay.c b/ffplay.c
index dbb6268..2e50920 100644
--- a/ffplay.c
+++ b/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 {
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index dbfb777..f96ae84 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 e9db33e..2a95975 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++;




More information about the ffmpeg-cvslog mailing list