[FFmpeg-cvslog] avformat/utils: compute_pkt_fields: Fix DTS for the case where has_b_frames is too large but the correct one is constant

Michael Niedermayer git at videolan.org
Sat Feb 22 14:37:33 CET 2014


ffmpeg | branch: master | Michael Niedermayer <michaelni at gmx.at> | Sat Feb 22 13:04:18 2014 +0100| [3c096751ffe85861cd88ee822b86f10155b7b639] | committer: Michael Niedermayer

avformat/utils: compute_pkt_fields: Fix DTS for the case where has_b_frames is too large but the correct one is constant

Fixes issue1.m2ts

Signed-off-by: Michael Niedermayer <michaelni at gmx.at>

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

 libavformat/avformat.h |    7 +++++++
 libavformat/utils.c    |   50 ++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 7abe15d..52eeb61 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -981,6 +981,13 @@ typedef struct AVStream {
      * Internal data to prevent doing update_initial_durations() twice
      */
     int update_initial_durations_done;
+
+    /**
+     * Internal data to generate dts from pts
+     */
+    int64_t pts_reorder_error[MAX_REORDER_DELAY+1];
+    uint8_t pts_reorder_error_count[MAX_REORDER_DELAY+1];
+
 } AVStream;
 
 AVRational av_stream_get_r_frame_rate(const AVStream *s);
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 357d95b..584edd3 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -962,6 +962,48 @@ static AVPacketList *get_next_pkt(AVFormatContext *s, AVStream *st, AVPacketList
     return NULL;
 }
 
+static int64_t select_from_pts_buffer(AVStream *st, int64_t *pts_buffer, int64_t dts) {
+    int onein_oneout = st->codec->codec_id != AV_CODEC_ID_H264 &&
+                       st->codec->codec_id != AV_CODEC_ID_HEVC;
+
+    if(!onein_oneout) {
+        int delay = st->codec->has_b_frames;
+        int i;
+
+        if (dts == AV_NOPTS_VALUE) {
+            int64_t best_score = INT64_MAX;
+            for (i = 0; i<delay; i++) {
+                if (st->pts_reorder_error_count[i]) {
+                    int64_t score = st->pts_reorder_error[i] / st->pts_reorder_error_count[i];
+                    if (score < best_score) {
+                        best_score = score;
+                        dts = pts_buffer[i];
+                    }
+                }
+            }
+        } else {
+            for (i = 0; i<delay; i++) {
+                if (pts_buffer[i] != AV_NOPTS_VALUE) {
+                    int64_t diff =  FFABS(pts_buffer[i] - dts)
+                                    + (uint64_t)st->pts_reorder_error[i];
+                    diff = FFMAX(diff, st->pts_reorder_error[i]);
+                    st->pts_reorder_error[i] = diff;
+                    st->pts_reorder_error_count[i]++;
+                    if (st->pts_reorder_error_count[i] > 250) {
+                        st->pts_reorder_error[i] >>= 1;
+                        st->pts_reorder_error_count[i] >>= 1;
+                    }
+                }
+            }
+        }
+    }
+
+    if (dts == AV_NOPTS_VALUE)
+        dts = pts_buffer[0];
+
+    return dts;
+}
+
 static void update_initial_timestamps(AVFormatContext *s, int stream_index,
                                       int64_t dts, int64_t pts, AVPacket *pkt)
 {
@@ -1004,8 +1046,8 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index,
             pts_buffer[0] = pktl->pkt.pts;
             for (i = 0; i<delay && pts_buffer[i] > pts_buffer[i + 1]; i++)
                 FFSWAP(int64_t, pts_buffer[i], pts_buffer[i + 1]);
-            if (pktl->pkt.dts == AV_NOPTS_VALUE)
-                pktl->pkt.dts = pts_buffer[0];
+
+            pktl->pkt.dts = select_from_pts_buffer(st, pts_buffer, pktl->pkt.dts);
         }
     }
 
@@ -1197,8 +1239,8 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
         st->pts_buffer[0] = pkt->pts;
         for (i = 0; i<delay && st->pts_buffer[i] > st->pts_buffer[i + 1]; i++)
             FFSWAP(int64_t, st->pts_buffer[i], st->pts_buffer[i + 1]);
-        if (pkt->dts == AV_NOPTS_VALUE)
-            pkt->dts = st->pts_buffer[0];
+
+        pkt->dts = select_from_pts_buffer(st, st->pts_buffer, pkt->dts);
     }
     // We skipped it above so we try here.
     if (!onein_oneout)



More information about the ffmpeg-cvslog mailing list