[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