Browse code

Implement guessed_pts in avcodec_decode_video2

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

Nicolas George authored on 2011/01/31 04:18:31
Showing 6 changed files
... ...
@@ -749,33 +749,6 @@ int read_file(const char *filename, char **bufptr, size_t *size)
749 749
     return 0;
750 750
 }
751 751
 
752
-void init_pts_correction(PtsCorrectionContext *ctx)
753
-{
754
-    ctx->num_faulty_pts = ctx->num_faulty_dts = 0;
755
-    ctx->last_pts = ctx->last_dts = INT64_MIN;
756
-}
757
-
758
-int64_t guess_correct_pts(PtsCorrectionContext *ctx, int64_t reordered_pts, int64_t dts)
759
-{
760
-    int64_t pts = AV_NOPTS_VALUE;
761
-
762
-    if (dts != AV_NOPTS_VALUE) {
763
-        ctx->num_faulty_dts += dts <= ctx->last_dts;
764
-        ctx->last_dts = dts;
765
-    }
766
-    if (reordered_pts != AV_NOPTS_VALUE) {
767
-        ctx->num_faulty_pts += reordered_pts <= ctx->last_pts;
768
-        ctx->last_pts = reordered_pts;
769
-    }
770
-    if ((ctx->num_faulty_pts<=ctx->num_faulty_dts || dts == AV_NOPTS_VALUE)
771
-       && reordered_pts != AV_NOPTS_VALUE)
772
-        pts = reordered_pts;
773
-    else
774
-        pts = dts;
775
-
776
-    return pts;
777
-}
778
-
779 752
 FILE *get_preset_file(char *filename, size_t filename_size,
780 753
                       const char *preset_name, int is_path, const char *codec_name)
781 754
 {
... ...
@@ -235,30 +235,6 @@ int read_yesno(void);
235 235
  */
236 236
 int read_file(const char *filename, char **bufptr, size_t *size);
237 237
 
238
-typedef struct {
239
-    int64_t num_faulty_pts; /// Number of incorrect PTS values so far
240
-    int64_t num_faulty_dts; /// Number of incorrect DTS values so far
241
-    int64_t last_pts;       /// PTS of the last frame
242
-    int64_t last_dts;       /// DTS of the last frame
243
-} PtsCorrectionContext;
244
-
245
-/**
246
- * Reset the state of the PtsCorrectionContext.
247
- */
248
-void init_pts_correction(PtsCorrectionContext *ctx);
249
-
250
-/**
251
- * Attempt to guess proper monotonic timestamps for decoded video frames
252
- * which might have incorrect times. Input timestamps may wrap around, in
253
- * which case the output will as well.
254
- *
255
- * @param pts the pts field of the decoded AVPacket, as passed through
256
- * AVCodecContext.reordered_opaque
257
- * @param dts the dts field of the decoded AVPacket
258
- * @return one of the input values, may be AV_NOPTS_VALUE
259
- */
260
-int64_t guess_correct_pts(PtsCorrectionContext *ctx, int64_t pts, int64_t dts);
261
-
262 238
 /**
263 239
  * Get a file corresponding to a preset file.
264 240
  *
... ...
@@ -320,7 +320,6 @@ typedef struct AVInputStream {
320 320
     int64_t       next_pts;  /* synthetic pts for cases where pkt.pts
321 321
                                 is not defined */
322 322
     int64_t       pts;       /* current pts */
323
-    PtsCorrectionContext pts_ctx;
324 323
     int is_start;            /* is 1 at the start and after a discontinuity */
325 324
     int showed_multi_packet_warning;
326 325
     int is_past_recording_time;
... ...
@@ -1561,7 +1560,7 @@ static int output_packet(AVInputStream *ist, int ist_index,
1561 1561
                         /* no picture yet */
1562 1562
                         goto discard_packet;
1563 1563
                     }
1564
-                    ist->next_pts = ist->pts = guess_correct_pts(&ist->pts_ctx, picture.pkt_pts, picture.pkt_dts);
1564
+                    ist->next_pts = ist->pts = picture.best_effort_timestamp;
1565 1565
                     if (ist->st->codec->time_base.num != 0) {
1566 1566
                         int ticks= ist->st->parser ? ist->st->parser->repeat_pict+1 : ist->st->codec->ticks_per_frame;
1567 1567
                         ist->next_pts += ((int64_t)AV_TIME_BASE *
... ...
@@ -2364,7 +2363,6 @@ static int transcode(AVFormatContext **output_files,
2364 2364
         st= ist->st;
2365 2365
         ist->pts = st->avg_frame_rate.num ? - st->codec->has_b_frames*AV_TIME_BASE / av_q2d(st->avg_frame_rate) : 0;
2366 2366
         ist->next_pts = AV_NOPTS_VALUE;
2367
-        init_pts_correction(&ist->pts_ctx);
2368 2367
         ist->is_start = 1;
2369 2368
     }
2370 2369
 
... ...
@@ -208,8 +208,6 @@ typedef struct VideoState {
208 208
     char filename[1024];
209 209
     int width, height, xleft, ytop;
210 210
 
211
-    PtsCorrectionContext pts_ctx;
212
-
213 211
 #if CONFIG_AVFILTER
214 212
     AVFilterContext *out_video_filter;          ///<the last filter in the video chain
215 213
 #endif
... ...
@@ -1286,7 +1284,7 @@ retry:
1286 1286
             if (is->audio_st && is->video_st)
1287 1287
                 av_diff = get_audio_clock(is) - get_video_clock(is);
1288 1288
             printf("%7.2f A-V:%7.3f s:%3.1f aq=%5dKB vq=%5dKB sq=%5dB f=%"PRId64"/%"PRId64"   \r",
1289
-                   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);
1289
+                   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);
1290 1290
             fflush(stdout);
1291 1291
             last_time = cur_time;
1292 1292
         }
... ...
@@ -1561,7 +1559,6 @@ static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacke
1561 1561
         is->video_current_pos = -1;
1562 1562
         SDL_UnlockMutex(is->pictq_mutex);
1563 1563
 
1564
-        init_pts_correction(&is->pts_ctx);
1565 1564
         is->frame_last_pts = AV_NOPTS_VALUE;
1566 1565
         is->frame_last_delay = 0;
1567 1566
         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
1576 1576
 
1577 1577
     if (got_picture) {
1578 1578
         if (decoder_reorder_pts == -1) {
1579
-            *pts = guess_correct_pts(&is->pts_ctx, frame->pkt_pts, frame->pkt_dts);
1579
+            *pts = frame->best_effort_timestamp;
1580 1580
         } else if (decoder_reorder_pts) {
1581 1581
             *pts = frame->pkt_pts;
1582 1582
         } else {
... ...
@@ -1026,6 +1026,13 @@ typedef struct AVPanScan{
1026 1026
      * - decoding: Read by user.\
1027 1027
      */\
1028 1028
     int64_t pkt_dts;\
1029
+\
1030
+    /**\
1031
+     * frame timestamp estimated using various heuristics, in stream time base\
1032
+     * - encoding: unused\
1033
+     * - decoding: set by libavcodec, read by user.\
1034
+     */\
1035
+    int64_t best_effort_timestamp;\
1029 1036
 
1030 1037
 
1031 1038
 #define FF_QSCALE_TYPE_MPEG1 0
... ...
@@ -2825,6 +2832,17 @@ typedef struct AVCodecContext {
2825 2825
      * - encoding: unused
2826 2826
      */
2827 2827
     AVPacket *pkt;
2828
+
2829
+    /**
2830
+     * Current statistics for PTS correction.
2831
+     * - decoding: maintained and used by libavcodec
2832
+     * - encoding: unused
2833
+     */
2834
+    int64_t pts_correction_num_faulty_pts; /// Number of incorrect PTS values so far
2835
+    int64_t pts_correction_num_faulty_dts; /// Number of incorrect DTS values so far
2836
+    int64_t pts_correction_last_pts;       /// PTS of the last frame
2837
+    int64_t pts_correction_last_dts;       /// DTS of the last frame
2838
+
2828 2839
 } AVCodecContext;
2829 2840
 
2830 2841
 /**
... ...
@@ -448,7 +448,7 @@ enum PixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum
448 448
 void avcodec_get_frame_defaults(AVFrame *pic){
449 449
     memset(pic, 0, sizeof(AVFrame));
450 450
 
451
-    pic->pts= AV_NOPTS_VALUE;
451
+    pic->pts = pic->best_effort_timestamp = AV_NOPTS_VALUE;
452 452
     pic->key_frame= 1;
453 453
 }
454 454
 
... ...
@@ -538,6 +538,11 @@ int attribute_align_arg avcodec_open(AVCodecContext *avctx, AVCodec *codec)
538 538
         goto free_and_end;
539 539
     }
540 540
 
541
+    avctx->pts_correction_num_faulty_pts =
542
+    avctx->pts_correction_num_faulty_dts = 0;
543
+    avctx->pts_correction_last_pts =
544
+    avctx->pts_correction_last_dts = INT64_MIN;
545
+
541 546
     if(avctx->codec->init){
542 547
         ret = avctx->codec->init(avctx);
543 548
         if (ret < 0) {
... ...
@@ -608,6 +613,39 @@ int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size,
608 608
     return ret;
609 609
 }
610 610
 
611
+/**
612
+ * Attempt to guess proper monotonic timestamps for decoded video frames
613
+ * which might have incorrect times. Input timestamps may wrap around, in
614
+ * which case the output will as well.
615
+ *
616
+ * @param pts the pts field of the decoded AVPacket, as passed through
617
+ * AVFrame.pkt_pts
618
+ * @param dts the dts field of the decoded AVPacket
619
+ * @return one of the input values, may be AV_NOPTS_VALUE
620
+ */
621
+static int64_t guess_correct_pts(AVCodecContext *ctx,
622
+                                 int64_t reordered_pts, int64_t dts)
623
+{
624
+    int64_t pts = AV_NOPTS_VALUE;
625
+
626
+    if (dts != AV_NOPTS_VALUE) {
627
+        ctx->pts_correction_num_faulty_dts += dts <= ctx->pts_correction_last_dts;
628
+        ctx->pts_correction_last_dts = dts;
629
+    }
630
+    if (reordered_pts != AV_NOPTS_VALUE) {
631
+        ctx->pts_correction_num_faulty_pts += reordered_pts <= ctx->pts_correction_last_pts;
632
+        ctx->pts_correction_last_pts = reordered_pts;
633
+    }
634
+    if ((ctx->pts_correction_num_faulty_pts<=ctx->pts_correction_num_faulty_dts || dts == AV_NOPTS_VALUE)
635
+       && reordered_pts != AV_NOPTS_VALUE)
636
+        pts = reordered_pts;
637
+    else
638
+        pts = dts;
639
+
640
+    return pts;
641
+}
642
+
643
+
611 644
 #if FF_API_VIDEO_OLD
612 645
 int attribute_align_arg avcodec_decode_video(AVCodecContext *avctx, AVFrame *picture,
613 646
                          int *got_picture_ptr,
... ...
@@ -643,6 +681,9 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi
643 643
         emms_c(); //needed to avoid an emms_c() call before every return;
644 644
 
645 645
         picture->pkt_dts= avpkt->dts;
646
+        picture->best_effort_timestamp = guess_correct_pts(avctx,
647
+                                                           picture->pkt_pts,
648
+                                                           picture->pkt_dts);
646 649
 
647 650
         if (*got_picture_ptr)
648 651
             avctx->frame_number++;