[FFmpeg-devel] [PATCH] MPEG-TS/-PS : better probing for duration and start-time for all streams in a container
Gaullier Nicolas
nicolas.gaullier at arkena.com
Wed May 14 18:25:13 CEST 2014
Carl,
Here below is a newly formated patch : it now passes tools/patcheck and I have git-applied it successfully. Hope it suits your requirements now.
Nicolas Gaullier
---
diff --git a/libavformat/utils.c b/libavformat/utils.c
index d84d605..7630501 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -1028,6 +1028,13 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index,
int64_t shift;
int i, delay;
+ if (pts != AV_NOPTS_VALUE) {
+ if (st->start_time == AV_NOPTS_VALUE) {
+ st->start_time = pts;
+ } else {
+ st->start_time = FFMIN(pts,st->start_time);
+ }
+ }
if (st->first_dts != AV_NOPTS_VALUE ||
dts == AV_NOPTS_VALUE ||
st->cur_dts == AV_NOPTS_VALUE ||
@@ -1065,9 +1072,6 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index,
pktl->pkt.dts = select_from_pts_buffer(st, pts_buffer, pktl->pkt.dts);
}
}
-
- if (st->start_time == AV_NOPTS_VALUE)
- st->start_time = pts;
}
static void update_initial_durations(AVFormatContext *s, AVStream *st,
@@ -2469,7 +2473,7 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
AVPacket pkt1, *pkt = &pkt1;
AVStream *st;
int read_size, i, ret;
- int64_t end_time;
+ int all_duration_valid = 0;
int64_t filesize, offset, duration;
int retry = 0;
@@ -2488,12 +2492,12 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
av_parser_close(st->parser);
st->parser = NULL;
}
+ st->info->last_duration = AV_NOPTS_VALUE;
}
- /* estimate the end time (duration) */
+ /* estimate the end time (duration) for all streams */
/* XXX: may need to support wrapping */
filesize = ic->pb ? avio_size(ic->pb) : 0;
- end_time = AV_NOPTS_VALUE;
do {
offset = filesize - (DURATION_MAX_READ_SIZE << retry);
if (offset < 0)
@@ -2502,11 +2506,11 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
avio_seek(ic->pb, offset, SEEK_SET);
read_size = 0;
for (;;) {
- if (read_size >= DURATION_MAX_READ_SIZE << (FFMAX(retry - 1, 0)))
+ if (read_size >= DURATION_MAX_READ_SIZE << retry)
break;
do {
- ret = ff_read_packet(ic, pkt);
+ ret = read_frame_internal(ic,pkt);
} while (ret == AVERROR(EAGAIN));
if (ret != 0)
break;
@@ -2515,7 +2519,7 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
if (pkt->pts != AV_NOPTS_VALUE &&
(st->start_time != AV_NOPTS_VALUE ||
st->first_dts != AV_NOPTS_VALUE)) {
- duration = end_time = pkt->pts;
+ duration = pkt->pts + pkt->duration;
if (st->start_time != AV_NOPTS_VALUE)
duration -= st->start_time;
else
@@ -2529,10 +2533,32 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
}
av_free_packet(pkt);
}
- } while (end_time == AV_NOPTS_VALUE &&
- filesize > (DURATION_MAX_READ_SIZE << retry) &&
+ /* check if all audio/video streams have valid duration */
+ all_duration_valid = 1;
+ for (i = 0; i < ic->nb_streams; i++) {
+ st = ic->streams[i];
+ switch (st->codec->codec_type) {
+ case AVMEDIA_TYPE_VIDEO:
+ case AVMEDIA_TYPE_AUDIO:
+ if (st->info->last_duration == AV_NOPTS_VALUE)
+ all_duration_valid = 0;
+ }
+ }
+ } while (!all_duration_valid &&
+ filesize > (DURATION_MAX_READ_SIZE << (retry+1)) &&
++retry <= DURATION_MAX_RETRY);
+ /* warn about audio/video streams which duration could not be estimated */
+ for (i = 0; i < ic->nb_streams; i++) {
+ st = ic->streams[i];
+ if (st->duration == AV_NOPTS_VALUE) {
+ switch (st->codec->codec_type) {
+ case AVMEDIA_TYPE_VIDEO:
+ case AVMEDIA_TYPE_AUDIO:
+ av_log(ic, AV_LOG_WARNING, "stream %d : no PTS found at end of file, duration not set\n", i);
+ }
+ }
+ }
fill_all_stream_timings(ic);
avio_seek(ic->pb, old_offset, SEEK_SET);
More information about the ffmpeg-devel
mailing list