From fe42f94ce1023f9c2f7e86404c60afcee5b078a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Mon, 17 Nov 2014 15:26:17 +0200 Subject: [PATCH] dashenc: Don't segment all video streams when one stream gets a keyframe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes sure that segments actually start at a keyframe (and makes sure we don't split segments twice in a row, with one segment consisting of only a handful of packets), when one stream uses b-frames while another one doesn't. Signed-off-by: Martin Storsjö --- libavformat/dashenc.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 41caf6dcff..065466169e 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -75,7 +75,6 @@ typedef struct DASHContext { int single_file; OutputStream *streams; int has_video, has_audio; - int nb_segments; int last_duration; int total_duration; char availability_start_time[100]; @@ -595,10 +594,13 @@ static void find_index_range(AVFormatContext *s, const char *dirname, *index_length = AV_RB32(&buf[0]); } -static int dash_flush(AVFormatContext *s, int final) +static int dash_flush(AVFormatContext *s, int final, int stream) { DASHContext *c = s->priv_data; int i, ret = 0; + int cur_flush_segment_index = 0; + if (stream >= 0) + cur_flush_segment_index = c->streams[stream].segment_index; for (i = 0; i < s->nb_streams; i++) { OutputStream *os = &c->streams[i]; @@ -609,6 +611,18 @@ static int dash_flush(AVFormatContext *s, int final) if (!os->packets_written) continue; + // Flush the single stream that got a keyframe right now. + // Flush all audio streams as well, in sync with video keyframes, + // but not the other video streams. + if (stream >= 0 && i != stream) { + if (s->streams[i]->codec->codec_type != AVMEDIA_TYPE_AUDIO) + continue; + // Make sure we don't flush audio streams multiple times, when + // all video streams are flushed one at a time. + if (c->has_video && os->segment_index > cur_flush_segment_index) + continue; + } + if (!c->single_file) { snprintf(filename, sizeof(filename), "chunk-stream%d-%05d.m4s", i, os->segment_index); snprintf(full_path, sizeof(full_path), "%s%s", c->dirname, filename); @@ -665,7 +679,7 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) DASHContext *c = s->priv_data; AVStream *st = s->streams[pkt->stream_index]; OutputStream *os = &c->streams[pkt->stream_index]; - int64_t seg_end_duration = (c->nb_segments + 1) * (int64_t) c->min_seg_duration; + int64_t seg_end_duration = (os->segment_index) * (int64_t) c->min_seg_duration; int ret; // If forcing the stream to start at 0, the mp4 muxer will set the start @@ -701,9 +715,8 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) } } - if ((ret = dash_flush(s, 0)) < 0) + if ((ret = dash_flush(s, 0, pkt->stream_index)) < 0) return ret; - c->nb_segments++; } if (!os->packets_written) @@ -729,7 +742,7 @@ static int dash_write_trailer(AVFormatContext *s) s->streams[0]->time_base, AV_TIME_BASE_Q); } - dash_flush(s, 1); + dash_flush(s, 1, -1); if (c->remove_at_exit) { char filename[1024];