-
-
Save rcombs/632c1767a3e5036f0480f380e04c062b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit e2ae5e0bbd7618d7b773b9da055f9b9ca1b53f83 | |
Author: rcombs <rcombs@rcombs.me> | |
Date: Thu Mar 19 23:48:10 2020 -0500 | |
lavf/mux: bypass interleave delay early when waiting on subtitle streams | |
This avoids long delays when converting live streams that have sparse subtitles | |
diff --git a/libavformat/avformat.h b/libavformat/avformat.h | |
index e91e7f1d33..26b501ac3a 100644 | |
--- a/libavformat/avformat.h | |
+++ b/libavformat/avformat.h | |
@@ -1951,6 +1951,15 @@ typedef struct AVFormatContext { | |
* - decoding: set by user | |
*/ | |
int max_probe_packets; | |
+ | |
+ /** | |
+ * Maximum buffering duration for interleaving sparse streams. | |
+ * | |
+ * @see max_interleave_delta | |
+ * | |
+ * Applies only to subtitle and data streams. | |
+ */ | |
+ int64_t max_sparse_interleave_delta; | |
} AVFormatContext; | |
#if FF_API_FORMAT_GET_SET | |
diff --git a/libavformat/mux.c b/libavformat/mux.c | |
index 44d5e5d1c0..88ee4995b1 100644 | |
--- a/libavformat/mux.c | |
+++ b/libavformat/mux.c | |
@@ -916,6 +916,7 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, | |
{ | |
AVPacketList *pktl; | |
int stream_count = 0; | |
+ int sparse_count = 0; | |
int noninterleaved_count = 0; | |
int i, ret; | |
int eof = flush; | |
@@ -928,6 +929,10 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, | |
for (i = 0; i < s->nb_streams; i++) { | |
if (s->streams[i]->last_in_packet_buffer) { | |
++stream_count; | |
+ } else if (s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE || | |
+ s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_DATA || | |
+ s->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC) { | |
+ ++sparse_count; | |
} else if (s->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_ATTACHMENT && | |
s->streams[i]->codecpar->codec_id != AV_CODEC_ID_VP8 && | |
s->streams[i]->codecpar->codec_id != AV_CODEC_ID_VP9) { | |
@@ -938,10 +943,13 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, | |
if (s->internal->nb_interleaved_streams == stream_count) | |
flush = 1; | |
- if (s->max_interleave_delta > 0 && | |
- s->internal->packet_buffer && | |
+ if (s->internal->packet_buffer && | |
!flush && | |
- s->internal->nb_interleaved_streams == stream_count+noninterleaved_count | |
+ ((s->max_interleave_delta > 0 && | |
+ s->internal->nb_interleaved_streams == stream_count+sparse_count+noninterleaved_count) || | |
+ (s->max_sparse_interleave_delta > 0 && | |
+ sparse_count && | |
+ s->internal->nb_interleaved_streams == stream_count+sparse_count)) | |
) { | |
AVPacket *top_pkt = &s->internal->packet_buffer->pkt; | |
int64_t delta_dts = INT64_MIN; | |
@@ -962,12 +970,23 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, | |
delta_dts = FFMAX(delta_dts, last_dts - top_dts); | |
} | |
- if (delta_dts > s->max_interleave_delta) { | |
+ if (s->max_interleave_delta > 0 && | |
+ delta_dts > s->max_interleave_delta && | |
+ s->internal->nb_interleaved_streams == stream_count+sparse_count+noninterleaved_count) { | |
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; | |
+ } else if (s->max_sparse_interleave_delta > 0 && | |
+ delta_dts > s->max_sparse_interleave_delta && | |
+ s->internal->nb_interleaved_streams == stream_count+sparse_count) { | |
+ av_log(s, AV_LOG_DEBUG, | |
+ "Delay between the first packet and last packet in the " | |
+ "muxing queue is %"PRId64" > %"PRId64" and all delayed " | |
+ "streams are sparse: forcing output\n", | |
+ delta_dts, s->max_sparse_interleave_delta); | |
+ flush = 1; | |
} | |
} | |
diff --git a/libavformat/options_table.h b/libavformat/options_table.h | |
index b4141564c8..b1c4662b57 100644 | |
--- a/libavformat/options_table.h | |
+++ b/libavformat/options_table.h | |
@@ -91,6 +91,7 @@ static const AVOption avformat_options[] = { | |
{"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 }, | |
+{"max_sparse_interleave_delta", "maximum buffering duration for interleaving sparse streams", OFFSET(max_sparse_interleave_delta), AV_OPT_TYPE_INT64, { .i64 = 1000000 }, 0, INT64_MAX, E }, | |
{"f_strict", "how strictly to follow the standards (deprecated; use strict, save via avconv)", OFFSET(strict_std_compliance), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, D|E, "strict"}, | |
{"strict", "how strictly to follow the standards", OFFSET(strict_std_compliance), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, D|E, "strict"}, | |
{"very", "strictly conform to a older more strict version of the spec or reference software", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_VERY_STRICT }, INT_MIN, INT_MAX, D|E, "strict"}, |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment