Browse code

Extract timestamp correction code from ffplay.c to cmdutils.c

Originally committed as revision 25241 to svn://svn.ffmpeg.org/ffmpeg/trunk

Alexander Strange authored on 2010/09/28 11:05:12
Showing 3 changed files
... ...
@@ -677,3 +677,30 @@ int read_file(const char *filename, char **bufptr, size_t *size)
677 677
     fclose(f);
678 678
     return 0;
679 679
 }
680
+
681
+void init_pts_correction(PtsCorrectionContext *ctx)
682
+{
683
+    ctx->num_faulty_pts = ctx->num_faulty_dts = 0;
684
+    ctx->last_pts = ctx->last_dts = INT64_MIN;
685
+}
686
+
687
+int64_t guess_correct_pts(PtsCorrectionContext *ctx, int64_t reordered_pts, int64_t dts)
688
+{
689
+    int64_t pts = AV_NOPTS_VALUE;
690
+
691
+    if (dts != AV_NOPTS_VALUE) {
692
+        ctx->num_faulty_dts += dts <= ctx->last_dts;
693
+        ctx->last_dts = dts;
694
+    }
695
+    if (reordered_pts != AV_NOPTS_VALUE) {
696
+        ctx->num_faulty_pts += reordered_pts <= ctx->last_pts;
697
+        ctx->last_pts = reordered_pts;
698
+    }
699
+    if ((ctx->num_faulty_pts<ctx->num_faulty_dts || dts == AV_NOPTS_VALUE)
700
+       && reordered_pts != AV_NOPTS_VALUE)
701
+        pts = reordered_pts;
702
+    else
703
+        pts = dts;
704
+
705
+    return pts;
706
+}
... ...
@@ -226,4 +226,28 @@ int read_yesno(void);
226 226
  */
227 227
 int read_file(const char *filename, char **bufptr, size_t *size);
228 228
 
229
+typedef struct {
230
+    int64_t num_faulty_pts; /// Number of incorrect PTS values so far
231
+    int64_t num_faulty_dts; /// Number of incorrect DTS values so far
232
+    int64_t last_pts;       /// PTS of the last frame
233
+    int64_t last_dts;       /// DTS of the last frame
234
+} PtsCorrectionContext;
235
+
236
+/**
237
+ * Resets the state of the PtsCorrectionContext.
238
+ */
239
+void init_pts_correction(PtsCorrectionContext *ctx);
240
+
241
+/**
242
+ * Attempts to guess proper monotonic timestamps for decoded video frames
243
+ * which might have incorrect times. Input timestamps may wrap around, in
244
+ * which case the output will as well.
245
+ *
246
+ * @param pts The pts field of the decoded AVPacket, as passed through
247
+ * AVCodecContext.reordered_opaque
248
+ * @param dts The dts field of the decoded AVPacket
249
+ * @return One of the input values. May be AV_NOPTS_VALUE.
250
+ */
251
+int64_t guess_correct_pts(PtsCorrectionContext *ctx, int64_t pts, int64_t dts);
252
+
229 253
 #endif /* FFMPEG_CMDUTILS_H */
... ...
@@ -207,10 +207,7 @@ typedef struct VideoState {
207 207
     char filename[1024];
208 208
     int width, height, xleft, ytop;
209 209
 
210
-    int64_t faulty_pts;
211
-    int64_t faulty_dts;
212
-    int64_t last_dts_for_fault_detection;
213
-    int64_t last_pts_for_fault_detection;
210
+    PtsCorrectionContext pts_ctx;
214 211
 
215 212
 #if CONFIG_AVFILTER
216 213
     AVFilterContext *out_video_filter;          ///<the last filter in the video chain
... ...
@@ -1286,7 +1283,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->faulty_dts, is->faulty_pts);
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);
1290 1290
             fflush(stdout);
1291 1291
             last_time = cur_time;
1292 1292
         }
... ...
@@ -1565,8 +1562,7 @@ static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacke
1565 1565
             is->video_current_pos= -1;
1566 1566
             SDL_UnlockMutex(is->pictq_mutex);
1567 1567
 
1568
-            is->last_dts_for_fault_detection=
1569
-            is->last_pts_for_fault_detection= INT64_MIN;
1568
+            init_pts_correction(&is->pts_ctx);
1570 1569
             is->frame_last_pts= AV_NOPTS_VALUE;
1571 1570
             is->frame_last_delay = 0;
1572 1571
             is->frame_timer = (double)av_gettime() / 1000000.0;
... ...
@@ -1583,26 +1579,19 @@ static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacke
1583 1583
                                     pkt);
1584 1584
 
1585 1585
         if (got_picture) {
1586
-            if(pkt->dts != AV_NOPTS_VALUE){
1587
-                is->faulty_dts += pkt->dts <= is->last_dts_for_fault_detection;
1588
-                is->last_dts_for_fault_detection= pkt->dts;
1586
+            if (decoder_reorder_pts == -1) {
1587
+                *pts = guess_correct_pts(&is->pts_ctx, frame->reordered_opaque, pkt->dts);
1588
+            } else if (decoder_reorder_pts) {
1589
+                *pts = frame->reordered_opaque;
1590
+            } else {
1591
+                *pts = pkt->dts;
1589 1592
             }
1590
-            if(frame->reordered_opaque != AV_NOPTS_VALUE){
1591
-                is->faulty_pts += frame->reordered_opaque <= is->last_pts_for_fault_detection;
1592
-                is->last_pts_for_fault_detection= frame->reordered_opaque;
1593
+
1594
+            if (*pts == AV_NOPTS_VALUE) {
1595
+                *pts = 0;
1593 1596
             }
1594 1597
         }
1595 1598
 
1596
-        if(   (   decoder_reorder_pts==1
1597
-               || (decoder_reorder_pts && is->faulty_pts<is->faulty_dts)
1598
-               || pkt->dts == AV_NOPTS_VALUE)
1599
-           && frame->reordered_opaque != AV_NOPTS_VALUE)
1600
-            *pts= frame->reordered_opaque;
1601
-        else if(pkt->dts != AV_NOPTS_VALUE)
1602
-            *pts= pkt->dts;
1603
-        else
1604
-            *pts= 0;
1605
-
1606 1599
 //            if (len1 < 0)
1607 1600
 //                break;
1608 1601
     if (got_picture){