summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2014-02-05 03:17:16 +0100
committerMichael Niedermayer <michaelni@gmx.at>2014-02-05 03:19:22 +0100
commit3adb5f8d8b4006f4188c9c4d6f0925988fadc2f4 (patch)
tree5fcd6d5b8350b26839ccea85b7c0db5178f8dcc2
parent6a4cc50980783013b19bfb2edaaca14cc38d5c92 (diff)
parentd9ae1031f5edbd25c8526b4cb51aba66d3bee931 (diff)
downloadffmpeg-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/APIchanges4
-rw-r--r--libavformat/avformat.h18
-rw-r--r--libavformat/mux.c44
-rw-r--r--libavformat/options_table.h1
-rw-r--r--libavformat/version.h4
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, \