diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2014-02-05 03:17:16 +0100 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2014-02-05 03:19:22 +0100 |
commit | 3adb5f8d8b4006f4188c9c4d6f0925988fadc2f4 (patch) | |
tree | 5fcd6d5b8350b26839ccea85b7c0db5178f8dcc2 | |
parent | 6a4cc50980783013b19bfb2edaaca14cc38d5c92 (diff) | |
parent | d9ae1031f5edbd25c8526b4cb51aba66d3bee931 (diff) | |
download | ffmpeg-3adb5f8d8b4006f4188c9c4d6f0925988fadc2f4.tar.gz |
Merge commit 'd9ae1031f5edbd25c8526b4cb51aba66d3bee931'
* commit 'd9ae1031f5edbd25c8526b4cb51aba66d3bee931':
lavf: improve handling of sparse streams when muxing
Conflicts:
doc/APIchanges
libavformat/avformat.h
libavformat/mux.c
libavformat/options_table.h
libavformat/version.h
See: 37ed5df5c5e06a55724fb9eb215da1594b648282
Merged-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | doc/APIchanges | 4 | ||||
-rw-r--r-- | libavformat/avformat.h | 18 | ||||
-rw-r--r-- | libavformat/mux.c | 44 | ||||
-rw-r--r-- | libavformat/options_table.h | 1 | ||||
-rw-r--r-- | libavformat/version.h | 4 |
5 files changed, 52 insertions, 19 deletions
diff --git a/doc/APIchanges b/doc/APIchanges index d75c977dfb..7a01b80f75 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,10 @@ libavutil: 2012-10-22 API changes, most recent first: +2014-02-xx - xxxxxxx - lavf 55.11.0 - avformat.h + Add AVFormatContext.max_interleave_delta for controlling amount of buffering + when interleaving. + 2014-02-02 - xxxxxxx - lavf 55.29.100 - avformat.h Add output_ts_offset muxing option to AVFormatContext. diff --git a/libavformat/avformat.h b/libavformat/avformat.h index fe3757a309..4d3cc1492b 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -1183,6 +1183,24 @@ typedef struct AVFormatContext { #define FF_FDEBUG_TS 0x0001 /** + * Maximum buffering duration for interleaving. + * + * To ensure all the streams are interleaved correctly, + * av_interleaved_write_frame() will wait until it has at least one packet + * for each stream before actually writing any packets to the output file. + * When some streams are "sparse" (i.e. there are large gaps between + * successive packets), this can result in excessive buffering. + * + * This field specifies the maximum difference between the timestamps of the + * first and the last packet in the muxing queue, above which libavformat + * will output a packet regardless of whether it has queued a packet for all + * the streams. + * + * Muxing only, set by the caller before avformat_write_header(). + */ + int64_t max_interleave_delta; + + /** * Transport stream id. * This will be moved into demuxer private options. Thus no API/ABI compatibility */ diff --git a/libavformat/mux.c b/libavformat/mux.c index 71a099f643..0b89406f4e 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -713,7 +713,6 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, { AVPacketList *pktl; int stream_count = 0, noninterleaved_count = 0; - int64_t delta_dts_max = 0; int i, ret; if (pkt) { @@ -730,27 +729,38 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, } } - if (s->internal->nb_interleaved_streams == stream_count) { + if (s->internal->nb_interleaved_streams == stream_count) flush = 1; - } else if (!flush) { - for (i=0; i < s->nb_streams; i++) { - if (s->streams[i]->last_in_packet_buffer) { - int64_t delta_dts = - av_rescale_q(s->streams[i]->last_in_packet_buffer->pkt.dts, - s->streams[i]->time_base, - AV_TIME_BASE_Q) - - av_rescale_q(s->packet_buffer->pkt.dts, - s->streams[s->packet_buffer->pkt.stream_index]->time_base, - AV_TIME_BASE_Q); - delta_dts_max= FFMAX(delta_dts_max, delta_dts); - } + + if (s->max_interleave_delta > 0 && s->packet_buffer && !flush) { + AVPacket *top_pkt = &s->packet_buffer->pkt; + int64_t delta_dts = INT64_MIN; + int64_t top_dts = av_rescale_q(top_pkt->dts, + s->streams[top_pkt->stream_index]->time_base, + AV_TIME_BASE_Q); + + for (i = 0; i < s->nb_streams; i++) { + int64_t last_dts; + const AVPacketList *last = s->streams[i]->last_in_packet_buffer; + + if (!last) + continue; + + last_dts = av_rescale_q(last->pkt.dts, + s->streams[i]->time_base, + AV_TIME_BASE_Q); + delta_dts = FFMAX(delta_dts, last_dts - top_dts); } - if (s->internal->nb_interleaved_streams == stream_count+noninterleaved_count && - delta_dts_max > 20*AV_TIME_BASE) { - av_log(s, AV_LOG_DEBUG, "flushing with %d noninterleaved\n", noninterleaved_count); + + if (delta_dts > s->max_interleave_delta) { + av_log(s, AV_LOG_DEBUG, + "Delay between the first packet and last packet in the " + "muxing queue is %"PRId64" > %"PRId64": forcing output\n", + delta_dts, s->max_interleave_delta); flush = 1; } } + if (stream_count && flush) { AVStream *st; pktl = s->packet_buffer; diff --git a/libavformat/options_table.h b/libavformat/options_table.h index b42a762738..ca30fd29e3 100644 --- a/libavformat/options_table.h +++ b/libavformat/options_table.h @@ -79,6 +79,7 @@ static const AVOption avformat_options[] = { {"flush_packets", "enable flushing of the I/O context after each packet", OFFSET(flush_packets), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, E}, {"metadata_header_padding", "set number of bytes to be written as padding in a metadata header", OFFSET(metadata_header_padding), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, E}, {"output_ts_offset", "set output timestamp offset", OFFSET(output_ts_offset), AV_OPT_TYPE_DURATION, {.i64 = 0}, -INT64_MAX, INT64_MAX, E}, +{"max_interleave_delta", "maximum buffering duration for interleaving", OFFSET(max_interleave_delta), AV_OPT_TYPE_INT64, { .i64 = 10000000 }, 0, INT64_MAX, E }, {NULL}, }; diff --git a/libavformat/version.h b/libavformat/version.h index 7a9aa4d4c7..0fcbe60eaa 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -30,8 +30,8 @@ #include "libavutil/version.h" #define LIBAVFORMAT_VERSION_MAJOR 55 -#define LIBAVFORMAT_VERSION_MINOR 29 -#define LIBAVFORMAT_VERSION_MICRO 101 +#define LIBAVFORMAT_VERSION_MINOR 30 +#define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ |