]> git.sesse.net Git - ffmpeg/blob - libavformat/dashenc.c
avformat/dashenc: allow setting fragment durations
[ffmpeg] / libavformat / dashenc.c
1 /*
2  * MPEG-DASH ISO BMFF segmenter
3  * Copyright (c) 2014 Martin Storsjo
4  * Copyright (c) 2018 Akamai Technologies, Inc.
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22
23 #include "config.h"
24 #if HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27
28 #include "libavutil/avassert.h"
29 #include "libavutil/avutil.h"
30 #include "libavutil/avstring.h"
31 #include "libavutil/intreadwrite.h"
32 #include "libavutil/mathematics.h"
33 #include "libavutil/opt.h"
34 #include "libavutil/parseutils.h"
35 #include "libavutil/rational.h"
36 #include "libavutil/time.h"
37 #include "libavutil/time_internal.h"
38
39 #include "av1.h"
40 #include "avc.h"
41 #include "avformat.h"
42 #include "avio_internal.h"
43 #include "hlsplaylist.h"
44 #if CONFIG_HTTP_PROTOCOL
45 #include "http.h"
46 #endif
47 #include "internal.h"
48 #include "isom.h"
49 #include "os_support.h"
50 #include "url.h"
51 #include "vpcc.h"
52 #include "dash.h"
53
54 typedef enum {
55     SEGMENT_TYPE_AUTO = 0,
56     SEGMENT_TYPE_MP4,
57     SEGMENT_TYPE_WEBM,
58     SEGMENT_TYPE_NB
59 } SegmentType;
60
61 enum {
62     FRAG_TYPE_NONE = 0,
63     FRAG_TYPE_EVERY_FRAME,
64     FRAG_TYPE_DURATION,
65     FRAG_TYPE_NB
66 };
67
68 typedef struct Segment {
69     char file[1024];
70     int64_t start_pos;
71     int range_length, index_length;
72     int64_t time;
73     double prog_date_time;
74     int64_t duration;
75     int n;
76 } Segment;
77
78 typedef struct AdaptationSet {
79     char id[10];
80     char *descriptor;
81     int64_t seg_duration;
82     int64_t frag_duration;
83     int frag_type;
84     enum AVMediaType media_type;
85     AVDictionary *metadata;
86     AVRational min_frame_rate, max_frame_rate;
87     int ambiguous_frame_rate;
88 } AdaptationSet;
89
90 typedef struct OutputStream {
91     AVFormatContext *ctx;
92     int ctx_inited, as_idx;
93     AVIOContext *out;
94     int packets_written;
95     char initfile[1024];
96     int64_t init_start_pos, pos;
97     int init_range_length;
98     int nb_segments, segments_size, segment_index;
99     int64_t seg_duration;
100     int64_t frag_duration;
101     int64_t last_duration;
102     Segment **segments;
103     int64_t first_pts, start_pts, max_pts;
104     int64_t last_dts, last_pts;
105     int bit_rate;
106     SegmentType segment_type;  /* segment type selected for this particular stream */
107     const char *format_name;
108     const char *extension_name;
109     const char *single_file_name;  /* file names selected for this particular stream */
110     const char *init_seg_name;
111     const char *media_seg_name;
112
113     char codec_str[100];
114     int written_len;
115     char filename[1024];
116     char full_path[1024];
117     char temp_path[1024];
118     double availability_time_offset;
119     int total_pkt_size;
120     int muxer_overhead;
121     int frag_type;
122 } OutputStream;
123
124 typedef struct DASHContext {
125     const AVClass *class;  /* Class for private options. */
126     char *adaptation_sets;
127     AdaptationSet *as;
128     int nb_as;
129     int window_size;
130     int extra_window_size;
131 #if FF_API_DASH_MIN_SEG_DURATION
132     int min_seg_duration;
133 #endif
134     int64_t seg_duration;
135     int64_t frag_duration;
136     int remove_at_exit;
137     int use_template;
138     int use_timeline;
139     int single_file;
140     OutputStream *streams;
141     int has_video;
142     int64_t last_duration;
143     int64_t total_duration;
144     char availability_start_time[100];
145     time_t start_time_s;
146     char dirname[1024];
147     const char *single_file_name;  /* file names as specified in options */
148     const char *init_seg_name;
149     const char *media_seg_name;
150     const char *utc_timing_url;
151     const char *method;
152     const char *user_agent;
153     int hls_playlist;
154     int http_persistent;
155     int master_playlist_created;
156     AVIOContext *mpd_out;
157     AVIOContext *m3u8_out;
158     int streaming;
159     int64_t timeout;
160     int index_correction;
161     AVDictionary *format_options;
162     int global_sidx;
163     SegmentType segment_type_option;  /* segment type as specified in options */
164     int ignore_io_errors;
165     int lhls;
166     int master_publish_rate;
167     int nr_of_streams_to_flush;
168     int nr_of_streams_flushed;
169     int frag_type;
170 } DASHContext;
171
172 static struct codec_string {
173     int id;
174     const char *str;
175 } codecs[] = {
176     { AV_CODEC_ID_VP8, "vp8" },
177     { AV_CODEC_ID_VP9, "vp9" },
178     { AV_CODEC_ID_VORBIS, "vorbis" },
179     { AV_CODEC_ID_OPUS, "opus" },
180     { AV_CODEC_ID_FLAC, "flac" },
181     { 0, NULL }
182 };
183
184 static struct format_string {
185     SegmentType segment_type;
186     const char *str;
187 } formats[] = {
188     { SEGMENT_TYPE_AUTO, "auto" },
189     { SEGMENT_TYPE_MP4, "mp4" },
190     { SEGMENT_TYPE_WEBM, "webm" },
191     { 0, NULL }
192 };
193
194 static int dashenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename,
195                            AVDictionary **options) {
196     DASHContext *c = s->priv_data;
197     int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
198     int err = AVERROR_MUXER_NOT_FOUND;
199     if (!*pb || !http_base_proto || !c->http_persistent) {
200         err = s->io_open(s, pb, filename, AVIO_FLAG_WRITE, options);
201 #if CONFIG_HTTP_PROTOCOL
202     } else {
203         URLContext *http_url_context = ffio_geturlcontext(*pb);
204         av_assert0(http_url_context);
205         err = ff_http_do_new_request(http_url_context, filename);
206         if (err < 0)
207             ff_format_io_close(s, pb);
208 #endif
209     }
210     return err;
211 }
212
213 static void dashenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename) {
214     DASHContext *c = s->priv_data;
215     int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
216
217     if (!*pb)
218         return;
219
220     if (!http_base_proto || !c->http_persistent) {
221         ff_format_io_close(s, pb);
222 #if CONFIG_HTTP_PROTOCOL
223     } else {
224         URLContext *http_url_context = ffio_geturlcontext(*pb);
225         av_assert0(http_url_context);
226         avio_flush(*pb);
227         ffurl_shutdown(http_url_context, AVIO_FLAG_WRITE);
228 #endif
229     }
230 }
231
232 static const char *get_format_str(SegmentType segment_type) {
233     int i;
234     for (i = 0; i < SEGMENT_TYPE_NB; i++)
235         if (formats[i].segment_type == segment_type)
236             return formats[i].str;
237     return NULL;
238 }
239
240 static const char *get_extension_str(SegmentType type, int single_file)
241 {
242     switch (type) {
243
244     case SEGMENT_TYPE_MP4:  return single_file ? "mp4" : "m4s";
245     case SEGMENT_TYPE_WEBM: return "webm";
246     default: return NULL;
247     }
248 }
249
250 static int handle_io_open_error(AVFormatContext *s, int err, char *url) {
251     DASHContext *c = s->priv_data;
252     char errbuf[AV_ERROR_MAX_STRING_SIZE];
253     av_strerror(err, errbuf, sizeof(errbuf));
254     av_log(s, c->ignore_io_errors ? AV_LOG_WARNING : AV_LOG_ERROR,
255            "Unable to open %s for writing: %s\n", url, errbuf);
256     return c->ignore_io_errors ? 0 : err;
257 }
258
259 static inline SegmentType select_segment_type(SegmentType segment_type, enum AVCodecID codec_id)
260 {
261     if (segment_type == SEGMENT_TYPE_AUTO) {
262         if (codec_id == AV_CODEC_ID_OPUS || codec_id == AV_CODEC_ID_VORBIS ||
263             codec_id == AV_CODEC_ID_VP8 || codec_id == AV_CODEC_ID_VP9) {
264             segment_type = SEGMENT_TYPE_WEBM;
265         } else {
266             segment_type = SEGMENT_TYPE_MP4;
267         }
268     }
269
270     return segment_type;
271 }
272
273 static int init_segment_types(AVFormatContext *s)
274 {
275     DASHContext *c = s->priv_data;
276     int has_mp4_streams = 0;
277     for (int i = 0; i < s->nb_streams; ++i) {
278         OutputStream *os = &c->streams[i];
279         SegmentType segment_type = select_segment_type(
280             c->segment_type_option, s->streams[i]->codecpar->codec_id);
281         os->segment_type = segment_type;
282         os->format_name = get_format_str(segment_type);
283         if (!os->format_name) {
284             av_log(s, AV_LOG_ERROR, "Could not select DASH segment type for stream %d\n", i);
285             return AVERROR_MUXER_NOT_FOUND;
286         }
287         os->extension_name = get_extension_str(segment_type, c->single_file);
288         if (!os->extension_name) {
289             av_log(s, AV_LOG_ERROR, "Could not get extension type for stream %d\n", i);
290             return AVERROR_MUXER_NOT_FOUND;
291         }
292
293         has_mp4_streams |= segment_type == SEGMENT_TYPE_MP4;
294     }
295
296     if (c->hls_playlist && !has_mp4_streams) {
297          av_log(s, AV_LOG_WARNING, "No mp4 streams, disabling HLS manifest generation\n");
298          c->hls_playlist = 0;
299     }
300
301     return 0;
302 }
303
304 static int check_file_extension(const char *filename, const char *extension) {
305     char *dot;
306     if (!filename || !extension)
307         return -1;
308     dot = strrchr(filename, '.');
309     if (dot && !strcmp(dot + 1, extension))
310         return 0;
311     return -1;
312 }
313
314 static void set_vp9_codec_str(AVFormatContext *s, AVCodecParameters *par,
315                               AVRational *frame_rate, char *str, int size) {
316     VPCC vpcc;
317     int ret = ff_isom_get_vpcc_features(s, par, frame_rate, &vpcc);
318     if (ret == 0) {
319         av_strlcatf(str, size, "vp09.%02d.%02d.%02d",
320                     vpcc.profile, vpcc.level, vpcc.bitdepth);
321     } else {
322         // Default to just vp9 in case of error while finding out profile or level
323         av_log(s, AV_LOG_WARNING, "Could not find VP9 profile and/or level\n");
324         av_strlcpy(str, "vp9", size);
325     }
326     return;
327 }
328
329 static void set_codec_str(AVFormatContext *s, AVCodecParameters *par,
330                           AVRational *frame_rate, char *str, int size)
331 {
332     const AVCodecTag *tags[2] = { NULL, NULL };
333     uint32_t tag;
334     int i;
335
336     // common Webm codecs are not part of RFC 6381
337     for (i = 0; codecs[i].id; i++)
338         if (codecs[i].id == par->codec_id) {
339             if (codecs[i].id == AV_CODEC_ID_VP9) {
340                 set_vp9_codec_str(s, par, frame_rate, str, size);
341             } else {
342                 av_strlcpy(str, codecs[i].str, size);
343             }
344             return;
345         }
346
347     // for codecs part of RFC 6381
348     if (par->codec_type == AVMEDIA_TYPE_VIDEO)
349         tags[0] = ff_codec_movvideo_tags;
350     else if (par->codec_type == AVMEDIA_TYPE_AUDIO)
351         tags[0] = ff_codec_movaudio_tags;
352     else
353         return;
354
355     tag = par->codec_tag;
356     if (!tag)
357         tag = av_codec_get_tag(tags, par->codec_id);
358     if (!tag)
359         return;
360     if (size < 5)
361         return;
362
363     AV_WL32(str, tag);
364     str[4] = '\0';
365     if (!strcmp(str, "mp4a") || !strcmp(str, "mp4v")) {
366         uint32_t oti;
367         tags[0] = ff_mp4_obj_type;
368         oti = av_codec_get_tag(tags, par->codec_id);
369         if (oti)
370             av_strlcatf(str, size, ".%02"PRIx32, oti);
371         else
372             return;
373
374         if (tag == MKTAG('m', 'p', '4', 'a')) {
375             if (par->extradata_size >= 2) {
376                 int aot = par->extradata[0] >> 3;
377                 if (aot == 31)
378                     aot = ((AV_RB16(par->extradata) >> 5) & 0x3f) + 32;
379                 av_strlcatf(str, size, ".%d", aot);
380             }
381         } else if (tag == MKTAG('m', 'p', '4', 'v')) {
382             // Unimplemented, should output ProfileLevelIndication as a decimal number
383             av_log(s, AV_LOG_WARNING, "Incomplete RFC 6381 codec string for mp4v\n");
384         }
385     } else if (!strcmp(str, "avc1")) {
386         uint8_t *tmpbuf = NULL;
387         uint8_t *extradata = par->extradata;
388         int extradata_size = par->extradata_size;
389         if (!extradata_size)
390             return;
391         if (extradata[0] != 1) {
392             AVIOContext *pb;
393             if (avio_open_dyn_buf(&pb) < 0)
394                 return;
395             if (ff_isom_write_avcc(pb, extradata, extradata_size) < 0) {
396                 ffio_free_dyn_buf(&pb);
397                 return;
398             }
399             extradata_size = avio_close_dyn_buf(pb, &extradata);
400             tmpbuf = extradata;
401         }
402
403         if (extradata_size >= 4)
404             av_strlcatf(str, size, ".%02x%02x%02x",
405                         extradata[1], extradata[2], extradata[3]);
406         av_free(tmpbuf);
407     } else if (!strcmp(str, "av01")) {
408         AV1SequenceParameters seq;
409         if (!par->extradata_size)
410             return;
411         if (ff_av1_parse_seq_header(&seq, par->extradata, par->extradata_size) < 0)
412             return;
413
414         av_strlcatf(str, size, ".%01u.%02u%s.%02u",
415                     seq.profile, seq.level, seq.tier ? "H" : "M", seq.bitdepth);
416         if (seq.color_description_present_flag)
417             av_strlcatf(str, size, ".%01u.%01u%01u%01u.%02u.%02u.%02u.%01u",
418                         seq.monochrome,
419                         seq.chroma_subsampling_x, seq.chroma_subsampling_y, seq.chroma_sample_position,
420                         seq.color_primaries, seq.transfer_characteristics, seq.matrix_coefficients,
421                         seq.color_range);
422     }
423 }
424
425 static int flush_dynbuf(DASHContext *c, OutputStream *os, int *range_length)
426 {
427     uint8_t *buffer;
428
429     if (!os->ctx->pb) {
430         return AVERROR(EINVAL);
431     }
432
433     // flush
434     av_write_frame(os->ctx, NULL);
435     avio_flush(os->ctx->pb);
436
437     if (!c->single_file) {
438         // write out to file
439         *range_length = avio_close_dyn_buf(os->ctx->pb, &buffer);
440         os->ctx->pb = NULL;
441         if (os->out)
442             avio_write(os->out, buffer + os->written_len, *range_length - os->written_len);
443         os->written_len = 0;
444         av_free(buffer);
445
446         // re-open buffer
447         return avio_open_dyn_buf(&os->ctx->pb);
448     } else {
449         *range_length = avio_tell(os->ctx->pb) - os->pos;
450         return 0;
451     }
452 }
453
454 static void set_http_options(AVDictionary **options, DASHContext *c)
455 {
456     if (c->method)
457         av_dict_set(options, "method", c->method, 0);
458     if (c->user_agent)
459         av_dict_set(options, "user_agent", c->user_agent, 0);
460     if (c->http_persistent)
461         av_dict_set_int(options, "multiple_requests", 1, 0);
462     if (c->timeout >= 0)
463         av_dict_set_int(options, "timeout", c->timeout, 0);
464 }
465
466 static void get_hls_playlist_name(char *playlist_name, int string_size,
467                                   const char *base_url, int id) {
468     if (base_url)
469         snprintf(playlist_name, string_size, "%smedia_%d.m3u8", base_url, id);
470     else
471         snprintf(playlist_name, string_size, "media_%d.m3u8", id);
472 }
473
474 static void get_start_index_number(OutputStream *os, DASHContext *c,
475                                    int *start_index, int *start_number) {
476     *start_index = 0;
477     *start_number = 1;
478     if (c->window_size) {
479         *start_index  = FFMAX(os->nb_segments   - c->window_size, 0);
480         *start_number = FFMAX(os->segment_index - c->window_size, 1);
481     }
482 }
483
484 static void write_hls_media_playlist(OutputStream *os, AVFormatContext *s,
485                                      int representation_id, int final,
486                                      char *prefetch_url) {
487     DASHContext *c = s->priv_data;
488     int timescale = os->ctx->streams[0]->time_base.den;
489     char temp_filename_hls[1024];
490     char filename_hls[1024];
491     AVDictionary *http_opts = NULL;
492     int target_duration = 0;
493     int ret = 0;
494     const char *proto = avio_find_protocol_name(c->dirname);
495     int use_rename = proto && !strcmp(proto, "file");
496     int i, start_index, start_number;
497     double prog_date_time = 0;
498
499     get_start_index_number(os, c, &start_index, &start_number);
500
501     if (!c->hls_playlist || start_index >= os->nb_segments ||
502         os->segment_type != SEGMENT_TYPE_MP4)
503         return;
504
505     get_hls_playlist_name(filename_hls, sizeof(filename_hls),
506                           c->dirname, representation_id);
507
508     snprintf(temp_filename_hls, sizeof(temp_filename_hls), use_rename ? "%s.tmp" : "%s", filename_hls);
509
510     set_http_options(&http_opts, c);
511     ret = dashenc_io_open(s, &c->m3u8_out, temp_filename_hls, &http_opts);
512     av_dict_free(&http_opts);
513     if (ret < 0) {
514         handle_io_open_error(s, ret, temp_filename_hls);
515         return;
516     }
517     for (i = start_index; i < os->nb_segments; i++) {
518         Segment *seg = os->segments[i];
519         double duration = (double) seg->duration / timescale;
520         if (target_duration <= duration)
521             target_duration = lrint(duration);
522     }
523
524     ff_hls_write_playlist_header(c->m3u8_out, 6, -1, target_duration,
525                                  start_number, PLAYLIST_TYPE_NONE, 0);
526
527     ff_hls_write_init_file(c->m3u8_out, os->initfile, c->single_file,
528                            os->init_range_length, os->init_start_pos);
529
530     for (i = start_index; i < os->nb_segments; i++) {
531         Segment *seg = os->segments[i];
532
533         if (prog_date_time == 0) {
534             if (os->nb_segments == 1)
535                 prog_date_time = c->start_time_s;
536             else
537                 prog_date_time = seg->prog_date_time;
538         }
539         seg->prog_date_time = prog_date_time;
540
541         ret = ff_hls_write_file_entry(c->m3u8_out, 0, c->single_file,
542                                 (double) seg->duration / timescale, 0,
543                                 seg->range_length, seg->start_pos, NULL,
544                                 c->single_file ? os->initfile : seg->file,
545                                 &prog_date_time, 0, 0, 0);
546         if (ret < 0) {
547             av_log(os->ctx, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n");
548         }
549     }
550
551     if (prefetch_url)
552         avio_printf(c->m3u8_out, "#EXT-X-PREFETCH:%s\n", prefetch_url);
553
554     if (final)
555         ff_hls_write_end_list(c->m3u8_out);
556
557     dashenc_io_close(s, &c->m3u8_out, temp_filename_hls);
558
559     if (use_rename)
560         if (avpriv_io_move(temp_filename_hls, filename_hls) < 0) {
561             av_log(os->ctx, AV_LOG_WARNING, "renaming file %s to %s failed\n\n", temp_filename_hls, filename_hls);
562         }
563 }
564
565 static int flush_init_segment(AVFormatContext *s, OutputStream *os)
566 {
567     DASHContext *c = s->priv_data;
568     int ret, range_length;
569
570     ret = flush_dynbuf(c, os, &range_length);
571     if (ret < 0)
572         return ret;
573
574     os->pos = os->init_range_length = range_length;
575     if (!c->single_file) {
576         char filename[1024];
577         snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile);
578         dashenc_io_close(s, &os->out, filename);
579     }
580     return 0;
581 }
582
583 static void dash_free(AVFormatContext *s)
584 {
585     DASHContext *c = s->priv_data;
586     int i, j;
587
588     if (c->as) {
589         for (i = 0; i < c->nb_as; i++) {
590             av_dict_free(&c->as[i].metadata);
591             av_freep(&c->as[i].descriptor);
592         }
593         av_freep(&c->as);
594         c->nb_as = 0;
595     }
596
597     if (!c->streams)
598         return;
599     for (i = 0; i < s->nb_streams; i++) {
600         OutputStream *os = &c->streams[i];
601         if (os->ctx && os->ctx->pb) {
602             if (!c->single_file)
603                 ffio_free_dyn_buf(&os->ctx->pb);
604             else
605                 avio_close(os->ctx->pb);
606         }
607         ff_format_io_close(s, &os->out);
608         avformat_free_context(os->ctx);
609         for (j = 0; j < os->nb_segments; j++)
610             av_free(os->segments[j]);
611         av_free(os->segments);
612         av_freep(&os->single_file_name);
613         av_freep(&os->init_seg_name);
614         av_freep(&os->media_seg_name);
615     }
616     av_freep(&c->streams);
617
618     ff_format_io_close(s, &c->mpd_out);
619     ff_format_io_close(s, &c->m3u8_out);
620 }
621
622 static void output_segment_list(OutputStream *os, AVIOContext *out, AVFormatContext *s,
623                                 int representation_id, int final)
624 {
625     DASHContext *c = s->priv_data;
626     int i, start_index, start_number;
627     get_start_index_number(os, c, &start_index, &start_number);
628
629     if (c->use_template) {
630         int timescale = c->use_timeline ? os->ctx->streams[0]->time_base.den : AV_TIME_BASE;
631         avio_printf(out, "\t\t\t\t<SegmentTemplate timescale=\"%d\" ", timescale);
632         if (!c->use_timeline) {
633             avio_printf(out, "duration=\"%"PRId64"\" ", os->seg_duration);
634             if (c->streaming && os->availability_time_offset)
635                 avio_printf(out, "availabilityTimeOffset=\"%.3f\" ",
636                             os->availability_time_offset);
637         }
638         avio_printf(out, "initialization=\"%s\" media=\"%s\" startNumber=\"%d\">\n", os->init_seg_name, os->media_seg_name, c->use_timeline ? start_number : 1);
639         if (c->use_timeline) {
640             int64_t cur_time = 0;
641             avio_printf(out, "\t\t\t\t\t<SegmentTimeline>\n");
642             for (i = start_index; i < os->nb_segments; ) {
643                 Segment *seg = os->segments[i];
644                 int repeat = 0;
645                 avio_printf(out, "\t\t\t\t\t\t<S ");
646                 if (i == start_index || seg->time != cur_time) {
647                     cur_time = seg->time;
648                     avio_printf(out, "t=\"%"PRId64"\" ", seg->time);
649                 }
650                 avio_printf(out, "d=\"%"PRId64"\" ", seg->duration);
651                 while (i + repeat + 1 < os->nb_segments &&
652                        os->segments[i + repeat + 1]->duration == seg->duration &&
653                        os->segments[i + repeat + 1]->time == os->segments[i + repeat]->time + os->segments[i + repeat]->duration)
654                     repeat++;
655                 if (repeat > 0)
656                     avio_printf(out, "r=\"%d\" ", repeat);
657                 avio_printf(out, "/>\n");
658                 i += 1 + repeat;
659                 cur_time += (1 + repeat) * seg->duration;
660             }
661             avio_printf(out, "\t\t\t\t\t</SegmentTimeline>\n");
662         }
663         avio_printf(out, "\t\t\t\t</SegmentTemplate>\n");
664     } else if (c->single_file) {
665         avio_printf(out, "\t\t\t\t<BaseURL>%s</BaseURL>\n", os->initfile);
666         avio_printf(out, "\t\t\t\t<SegmentList timescale=\"%d\" duration=\"%"PRId64"\" startNumber=\"%d\">\n", AV_TIME_BASE, FFMIN(os->seg_duration, os->last_duration), start_number);
667         avio_printf(out, "\t\t\t\t\t<Initialization range=\"%"PRId64"-%"PRId64"\" />\n", os->init_start_pos, os->init_start_pos + os->init_range_length - 1);
668         for (i = start_index; i < os->nb_segments; i++) {
669             Segment *seg = os->segments[i];
670             avio_printf(out, "\t\t\t\t\t<SegmentURL mediaRange=\"%"PRId64"-%"PRId64"\" ", seg->start_pos, seg->start_pos + seg->range_length - 1);
671             if (seg->index_length)
672                 avio_printf(out, "indexRange=\"%"PRId64"-%"PRId64"\" ", seg->start_pos, seg->start_pos + seg->index_length - 1);
673             avio_printf(out, "/>\n");
674         }
675         avio_printf(out, "\t\t\t\t</SegmentList>\n");
676     } else {
677         avio_printf(out, "\t\t\t\t<SegmentList timescale=\"%d\" duration=\"%"PRId64"\" startNumber=\"%d\">\n", AV_TIME_BASE, FFMIN(os->seg_duration, os->last_duration), start_number);
678         avio_printf(out, "\t\t\t\t\t<Initialization sourceURL=\"%s\" />\n", os->initfile);
679         for (i = start_index; i < os->nb_segments; i++) {
680             Segment *seg = os->segments[i];
681             avio_printf(out, "\t\t\t\t\t<SegmentURL media=\"%s\" />\n", seg->file);
682         }
683         avio_printf(out, "\t\t\t\t</SegmentList>\n");
684     }
685     if (!c->lhls || final) {
686         write_hls_media_playlist(os, s, representation_id, final, NULL);
687     }
688
689 }
690
691 static char *xmlescape(const char *str) {
692     int outlen = strlen(str)*3/2 + 6;
693     char *out = av_realloc(NULL, outlen + 1);
694     int pos = 0;
695     if (!out)
696         return NULL;
697     for (; *str; str++) {
698         if (pos + 6 > outlen) {
699             char *tmp;
700             outlen = 2 * outlen + 6;
701             tmp = av_realloc(out, outlen + 1);
702             if (!tmp) {
703                 av_free(out);
704                 return NULL;
705             }
706             out = tmp;
707         }
708         if (*str == '&') {
709             memcpy(&out[pos], "&amp;", 5);
710             pos += 5;
711         } else if (*str == '<') {
712             memcpy(&out[pos], "&lt;", 4);
713             pos += 4;
714         } else if (*str == '>') {
715             memcpy(&out[pos], "&gt;", 4);
716             pos += 4;
717         } else if (*str == '\'') {
718             memcpy(&out[pos], "&apos;", 6);
719             pos += 6;
720         } else if (*str == '\"') {
721             memcpy(&out[pos], "&quot;", 6);
722             pos += 6;
723         } else {
724             out[pos++] = *str;
725         }
726     }
727     out[pos] = '\0';
728     return out;
729 }
730
731 static void write_time(AVIOContext *out, int64_t time)
732 {
733     int seconds = time / AV_TIME_BASE;
734     int fractions = time % AV_TIME_BASE;
735     int minutes = seconds / 60;
736     int hours = minutes / 60;
737     seconds %= 60;
738     minutes %= 60;
739     avio_printf(out, "PT");
740     if (hours)
741         avio_printf(out, "%dH", hours);
742     if (hours || minutes)
743         avio_printf(out, "%dM", minutes);
744     avio_printf(out, "%d.%dS", seconds, fractions / (AV_TIME_BASE / 10));
745 }
746
747 static void format_date_now(char *buf, int size)
748 {
749     struct tm *ptm, tmbuf;
750     int64_t time_us = av_gettime();
751     int64_t time_ms = time_us / 1000;
752     const time_t time_s = time_ms / 1000;
753     int millisec = time_ms - (time_s * 1000);
754     ptm = gmtime_r(&time_s, &tmbuf);
755     if (ptm) {
756         int len;
757         if (!strftime(buf, size, "%Y-%m-%dT%H:%M:%S", ptm)) {
758             buf[0] = '\0';
759             return;
760         }
761         len = strlen(buf);
762         snprintf(buf + len, size - len, ".%03dZ", millisec);
763     }
764 }
765
766 static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_index,
767                                 int final)
768 {
769     DASHContext *c = s->priv_data;
770     AdaptationSet *as = &c->as[as_index];
771     AVDictionaryEntry *lang, *role;
772     int i;
773
774     avio_printf(out, "\t\t<AdaptationSet id=\"%s\" contentType=\"%s\" segmentAlignment=\"true\" bitstreamSwitching=\"true\"",
775                 as->id, as->media_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio");
776     if (as->media_type == AVMEDIA_TYPE_VIDEO && as->max_frame_rate.num && !as->ambiguous_frame_rate && av_cmp_q(as->min_frame_rate, as->max_frame_rate) < 0)
777         avio_printf(out, " maxFrameRate=\"%d/%d\"", as->max_frame_rate.num, as->max_frame_rate.den);
778     lang = av_dict_get(as->metadata, "language", NULL, 0);
779     if (lang)
780         avio_printf(out, " lang=\"%s\"", lang->value);
781     avio_printf(out, ">\n");
782
783     role = av_dict_get(as->metadata, "role", NULL, 0);
784     if (role)
785         avio_printf(out, "\t\t\t<Role schemeIdUri=\"urn:mpeg:dash:role:2011\" value=\"%s\"/>\n", role->value);
786     if (as->descriptor)
787         avio_printf(out, "\t\t\t%s\n", as->descriptor);
788     for (i = 0; i < s->nb_streams; i++) {
789         OutputStream *os = &c->streams[i];
790         char bandwidth_str[64] = {'\0'};
791
792         if (os->as_idx - 1 != as_index)
793             continue;
794
795         if (os->bit_rate > 0)
796             snprintf(bandwidth_str, sizeof(bandwidth_str), " bandwidth=\"%d\"",
797                      os->bit_rate);
798
799         if (as->media_type == AVMEDIA_TYPE_VIDEO) {
800             AVStream *st = s->streams[i];
801             avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"video/%s\" codecs=\"%s\"%s width=\"%d\" height=\"%d\"",
802                 i, os->format_name, os->codec_str, bandwidth_str, s->streams[i]->codecpar->width, s->streams[i]->codecpar->height);
803             if (st->avg_frame_rate.num)
804                 avio_printf(out, " frameRate=\"%d/%d\"", st->avg_frame_rate.num, st->avg_frame_rate.den);
805             avio_printf(out, ">\n");
806         } else {
807             avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"audio/%s\" codecs=\"%s\"%s audioSamplingRate=\"%d\">\n",
808                 i, os->format_name, os->codec_str, bandwidth_str, s->streams[i]->codecpar->sample_rate);
809             avio_printf(out, "\t\t\t\t<AudioChannelConfiguration schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\" value=\"%d\" />\n",
810                 s->streams[i]->codecpar->channels);
811         }
812         output_segment_list(os, out, s, i, final);
813         avio_printf(out, "\t\t\t</Representation>\n");
814     }
815     avio_printf(out, "\t\t</AdaptationSet>\n");
816
817     return 0;
818 }
819
820 static int add_adaptation_set(AVFormatContext *s, AdaptationSet **as, enum AVMediaType type)
821 {
822     DASHContext *c = s->priv_data;
823
824     void *mem = av_realloc(c->as, sizeof(*c->as) * (c->nb_as + 1));
825     if (!mem)
826         return AVERROR(ENOMEM);
827     c->as = mem;
828     ++c->nb_as;
829
830     *as = &c->as[c->nb_as - 1];
831     memset(*as, 0, sizeof(**as));
832     (*as)->media_type = type;
833     (*as)->frag_type = -1;
834
835     return 0;
836 }
837
838 static int adaptation_set_add_stream(AVFormatContext *s, int as_idx, int i)
839 {
840     DASHContext *c = s->priv_data;
841     AdaptationSet *as = &c->as[as_idx - 1];
842     OutputStream *os = &c->streams[i];
843
844     if (as->media_type != s->streams[i]->codecpar->codec_type) {
845         av_log(s, AV_LOG_ERROR, "Codec type of stream %d doesn't match AdaptationSet's media type\n", i);
846         return AVERROR(EINVAL);
847     } else if (os->as_idx) {
848         av_log(s, AV_LOG_ERROR, "Stream %d is already assigned to an AdaptationSet\n", i);
849         return AVERROR(EINVAL);
850     }
851     os->as_idx = as_idx;
852
853     return 0;
854 }
855
856 static int parse_adaptation_sets(AVFormatContext *s)
857 {
858     DASHContext *c = s->priv_data;
859     const char *p = c->adaptation_sets;
860     enum { new_set, parse_default, parsing_streams, parse_seg_duration, parse_frag_duration } state;
861     AdaptationSet *as;
862     int i, n, ret;
863
864     // default: one AdaptationSet for each stream
865     if (!p) {
866         for (i = 0; i < s->nb_streams; i++) {
867             if ((ret = add_adaptation_set(s, &as, s->streams[i]->codecpar->codec_type)) < 0)
868                 return ret;
869             snprintf(as->id, sizeof(as->id), "%d", i);
870
871             c->streams[i].as_idx = c->nb_as;
872         }
873         goto end;
874     }
875
876     // syntax id=0,streams=0,1,2 id=1,streams=3,4 and so on
877     // option id=0,descriptor=descriptor_str,streams=0,1,2 and so on
878     // option id=0,seg_duration=2.5,frag_duration=0.5,streams=0,1,2 and so on
879     // descriptor is useful to the scheme defined by ISO/IEC 23009-1:2014/Amd.2:2015
880     // descriptor_str should be a self-closing xml tag.
881     // seg_duration and frag_duration have the same syntax as the global options of
882     // the same name, and the former have precedence over them if set.
883     state = new_set;
884     while (*p) {
885         if (*p == ' ') {
886             p++;
887             continue;
888         } else if (state == new_set && av_strstart(p, "id=", &p)) {
889
890             if ((ret = add_adaptation_set(s, &as, AVMEDIA_TYPE_UNKNOWN)) < 0)
891                 return ret;
892
893             n = strcspn(p, ",");
894             snprintf(as->id, sizeof(as->id), "%.*s", n, p);
895
896             p += n;
897             if (*p)
898                 p++;
899             state = parse_default;
900         } else if (state != new_set && av_strstart(p, "seg_duration=", &p)) {
901             state = parse_seg_duration;
902         } else if (state != new_set && av_strstart(p, "frag_duration=", &p)) {
903             state = parse_frag_duration;
904         } else if (state == parse_seg_duration || state == parse_frag_duration) {
905             char str[32];
906             int64_t usecs = 0;
907
908             n = strcspn(p, ",");
909             snprintf(str, sizeof(str), "%.*s", n, p);
910             p += n;
911             if (*p)
912                 p++;
913
914             ret = av_parse_time(&usecs, str, 1);
915             if (ret < 0) {
916                 av_log(s, AV_LOG_ERROR, "Unable to parse option value \"%s\" as duration\n", str);
917                 return ret;
918             }
919
920             if (state == parse_seg_duration)
921                 as->seg_duration = usecs;
922             else
923                 as->frag_duration = usecs;
924             state = parse_default;
925         } else if (state != new_set && av_strstart(p, "frag_type=", &p)) {
926             char type_str[16];
927
928             n = strcspn(p, ",");
929             snprintf(type_str, sizeof(type_str), "%.*s", n, p);
930             p += n;
931             if (*p)
932                 p++;
933
934             if (!strcmp(type_str, "duration"))
935                 as->frag_type = FRAG_TYPE_DURATION;
936             else if (!strcmp(type_str, "every_frame"))
937                 as->frag_type = FRAG_TYPE_EVERY_FRAME;
938             else if (!strcmp(type_str, "none"))
939                 as->frag_type = FRAG_TYPE_NONE;
940             else {
941                 av_log(s, AV_LOG_ERROR, "Unable to parse option value \"%s\" as fragment type\n", type_str);
942                 return ret;
943             }
944             state = parse_default;
945         } else if (state != new_set && av_strstart(p, "descriptor=", &p)) {
946             n = strcspn(p, ">") + 1; //followed by one comma, so plus 1
947             if (n < strlen(p)) {
948                 as->descriptor = av_strndup(p, n);
949             } else {
950                 av_log(s, AV_LOG_ERROR, "Parse error, descriptor string should be a self-closing xml tag\n");
951                 return AVERROR(EINVAL);
952             }
953             p += n;
954             if (*p)
955                 p++;
956             state = parse_default;
957         } else if ((state != new_set) && av_strstart(p, "streams=", &p)) { //descriptor and durations are optional
958             state = parsing_streams;
959         } else if (state == parsing_streams) {
960             AdaptationSet *as = &c->as[c->nb_as - 1];
961             char idx_str[8], *end_str;
962
963             n = strcspn(p, " ,");
964             snprintf(idx_str, sizeof(idx_str), "%.*s", n, p);
965             p += n;
966
967             // if value is "a" or "v", map all streams of that type
968             if (as->media_type == AVMEDIA_TYPE_UNKNOWN && (idx_str[0] == 'v' || idx_str[0] == 'a')) {
969                 enum AVMediaType type = (idx_str[0] == 'v') ? AVMEDIA_TYPE_VIDEO : AVMEDIA_TYPE_AUDIO;
970                 av_log(s, AV_LOG_DEBUG, "Map all streams of type %s\n", idx_str);
971
972                 for (i = 0; i < s->nb_streams; i++) {
973                     if (s->streams[i]->codecpar->codec_type != type)
974                         continue;
975
976                     as->media_type = s->streams[i]->codecpar->codec_type;
977
978                     if ((ret = adaptation_set_add_stream(s, c->nb_as, i)) < 0)
979                         return ret;
980                 }
981             } else { // select single stream
982                 i = strtol(idx_str, &end_str, 10);
983                 if (idx_str == end_str || i < 0 || i >= s->nb_streams) {
984                     av_log(s, AV_LOG_ERROR, "Selected stream \"%s\" not found!\n", idx_str);
985                     return AVERROR(EINVAL);
986                 }
987                 av_log(s, AV_LOG_DEBUG, "Map stream %d\n", i);
988
989                 if (as->media_type == AVMEDIA_TYPE_UNKNOWN) {
990                     as->media_type = s->streams[i]->codecpar->codec_type;
991                 }
992
993                 if ((ret = adaptation_set_add_stream(s, c->nb_as, i)) < 0)
994                     return ret;
995             }
996
997             if (*p == ' ')
998                 state = new_set;
999             if (*p)
1000                 p++;
1001         } else {
1002             return AVERROR(EINVAL);
1003         }
1004     }
1005
1006 end:
1007     // check for unassigned streams
1008     for (i = 0; i < s->nb_streams; i++) {
1009         OutputStream *os = &c->streams[i];
1010         if (!os->as_idx) {
1011             av_log(s, AV_LOG_ERROR, "Stream %d is not mapped to an AdaptationSet\n", i);
1012             return AVERROR(EINVAL);
1013         }
1014     }
1015     return 0;
1016 }
1017
1018 static int write_manifest(AVFormatContext *s, int final)
1019 {
1020     DASHContext *c = s->priv_data;
1021     AVIOContext *out;
1022     char temp_filename[1024];
1023     int ret, i;
1024     const char *proto = avio_find_protocol_name(s->url);
1025     int use_rename = proto && !strcmp(proto, "file");
1026     static unsigned int warned_non_file = 0;
1027     AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
1028     AVDictionary *opts = NULL;
1029
1030     if (!use_rename && !warned_non_file++)
1031         av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this may lead to races and temporary partial files\n");
1032
1033     snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", s->url);
1034     set_http_options(&opts, c);
1035     ret = dashenc_io_open(s, &c->mpd_out, temp_filename, &opts);
1036     av_dict_free(&opts);
1037     if (ret < 0) {
1038         return handle_io_open_error(s, ret, temp_filename);
1039     }
1040     out = c->mpd_out;
1041     avio_printf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
1042     avio_printf(out, "<MPD xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
1043                 "\txmlns=\"urn:mpeg:dash:schema:mpd:2011\"\n"
1044                 "\txmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
1045                 "\txsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd\"\n"
1046                 "\tprofiles=\"urn:mpeg:dash:profile:isoff-live:2011\"\n"
1047                 "\ttype=\"%s\"\n", final ? "static" : "dynamic");
1048     if (final) {
1049         avio_printf(out, "\tmediaPresentationDuration=\"");
1050         write_time(out, c->total_duration);
1051         avio_printf(out, "\"\n");
1052     } else {
1053         int64_t update_period = c->last_duration / AV_TIME_BASE;
1054         char now_str[100];
1055         if (c->use_template && !c->use_timeline)
1056             update_period = 500;
1057         avio_printf(out, "\tminimumUpdatePeriod=\"PT%"PRId64"S\"\n", update_period);
1058         avio_printf(out, "\tsuggestedPresentationDelay=\"PT%"PRId64"S\"\n", c->last_duration / AV_TIME_BASE);
1059         if (c->availability_start_time[0])
1060             avio_printf(out, "\tavailabilityStartTime=\"%s\"\n", c->availability_start_time);
1061         format_date_now(now_str, sizeof(now_str));
1062         if (now_str[0])
1063             avio_printf(out, "\tpublishTime=\"%s\"\n", now_str);
1064         if (c->window_size && c->use_template) {
1065             avio_printf(out, "\ttimeShiftBufferDepth=\"");
1066             write_time(out, c->last_duration * c->window_size);
1067             avio_printf(out, "\"\n");
1068         }
1069     }
1070     avio_printf(out, "\tminBufferTime=\"");
1071     write_time(out, c->last_duration * 2);
1072     avio_printf(out, "\">\n");
1073     avio_printf(out, "\t<ProgramInformation>\n");
1074     if (title) {
1075         char *escaped = xmlescape(title->value);
1076         avio_printf(out, "\t\t<Title>%s</Title>\n", escaped);
1077         av_free(escaped);
1078     }
1079     avio_printf(out, "\t</ProgramInformation>\n");
1080
1081     if (c->window_size && s->nb_streams > 0 && c->streams[0].nb_segments > 0 && !c->use_template) {
1082         OutputStream *os = &c->streams[0];
1083         int start_index = FFMAX(os->nb_segments - c->window_size, 0);
1084         int64_t start_time = av_rescale_q(os->segments[start_index]->time, s->streams[0]->time_base, AV_TIME_BASE_Q);
1085         avio_printf(out, "\t<Period id=\"0\" start=\"");
1086         write_time(out, start_time);
1087         avio_printf(out, "\">\n");
1088     } else {
1089         avio_printf(out, "\t<Period id=\"0\" start=\"PT0.0S\">\n");
1090     }
1091
1092     for (i = 0; i < c->nb_as; i++) {
1093         if ((ret = write_adaptation_set(s, out, i, final)) < 0)
1094             return ret;
1095     }
1096     avio_printf(out, "\t</Period>\n");
1097
1098     if (c->utc_timing_url)
1099         avio_printf(out, "\t<UTCTiming schemeIdUri=\"urn:mpeg:dash:utc:http-xsdate:2014\" value=\"%s\"/>\n", c->utc_timing_url);
1100
1101     avio_printf(out, "</MPD>\n");
1102     avio_flush(out);
1103     dashenc_io_close(s, &c->mpd_out, temp_filename);
1104
1105     if (use_rename) {
1106         if ((ret = avpriv_io_move(temp_filename, s->url)) < 0)
1107             return ret;
1108     }
1109
1110     if (c->hls_playlist) {
1111         char filename_hls[1024];
1112         const char *audio_group = "A1";
1113         char audio_codec_str[128] = "\0";
1114         int is_default = 1;
1115         int max_audio_bitrate = 0;
1116
1117         // Publish master playlist only the configured rate
1118         if (c->master_playlist_created && (!c->master_publish_rate ||
1119              c->streams[0].segment_index % c->master_publish_rate))
1120             return 0;
1121
1122         if (*c->dirname)
1123             snprintf(filename_hls, sizeof(filename_hls), "%smaster.m3u8", c->dirname);
1124         else
1125             snprintf(filename_hls, sizeof(filename_hls), "master.m3u8");
1126
1127         snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", filename_hls);
1128
1129         set_http_options(&opts, c);
1130         ret = dashenc_io_open(s, &c->m3u8_out, temp_filename, &opts);
1131         av_dict_free(&opts);
1132         if (ret < 0) {
1133             return handle_io_open_error(s, ret, temp_filename);
1134         }
1135
1136         ff_hls_write_playlist_version(c->m3u8_out, 7);
1137
1138         for (i = 0; i < s->nb_streams; i++) {
1139             char playlist_file[64];
1140             AVStream *st = s->streams[i];
1141             OutputStream *os = &c->streams[i];
1142             if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
1143                 continue;
1144             if (os->segment_type != SEGMENT_TYPE_MP4)
1145                 continue;
1146             get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, i);
1147             ff_hls_write_audio_rendition(c->m3u8_out, (char *)audio_group,
1148                                          playlist_file, NULL, i, is_default);
1149             max_audio_bitrate = FFMAX(st->codecpar->bit_rate +
1150                                       os->muxer_overhead, max_audio_bitrate);
1151             if (!av_strnstr(audio_codec_str, os->codec_str, sizeof(audio_codec_str))) {
1152                 if (strlen(audio_codec_str))
1153                     av_strlcat(audio_codec_str, ",", sizeof(audio_codec_str));
1154                 av_strlcat(audio_codec_str, os->codec_str, sizeof(audio_codec_str));
1155             }
1156             is_default = 0;
1157         }
1158
1159         for (i = 0; i < s->nb_streams; i++) {
1160             char playlist_file[64];
1161             char codec_str[128];
1162             AVStream *st = s->streams[i];
1163             OutputStream *os = &c->streams[i];
1164             char *agroup = NULL;
1165             char *codec_str_ptr = NULL;
1166             int stream_bitrate = st->codecpar->bit_rate + os->muxer_overhead;
1167             if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)
1168                 continue;
1169             if (os->segment_type != SEGMENT_TYPE_MP4)
1170                 continue;
1171             av_strlcpy(codec_str, os->codec_str, sizeof(codec_str));
1172             if (max_audio_bitrate) {
1173                 agroup = (char *)audio_group;
1174                 stream_bitrate += max_audio_bitrate;
1175                 av_strlcat(codec_str, ",", sizeof(codec_str));
1176                 av_strlcat(codec_str, audio_codec_str, sizeof(codec_str));
1177             }
1178             if (st->codecpar->codec_id != AV_CODEC_ID_HEVC) {
1179                 codec_str_ptr = codec_str;
1180             }
1181             get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, i);
1182             ff_hls_write_stream_info(st, c->m3u8_out, stream_bitrate,
1183                                      playlist_file, agroup,
1184                                      codec_str_ptr, NULL);
1185         }
1186         dashenc_io_close(s, &c->m3u8_out, temp_filename);
1187         if (use_rename)
1188             if ((ret = avpriv_io_move(temp_filename, filename_hls)) < 0)
1189                 return ret;
1190         c->master_playlist_created = 1;
1191     }
1192
1193     return 0;
1194 }
1195
1196 static int dict_copy_entry(AVDictionary **dst, const AVDictionary *src, const char *key)
1197 {
1198     AVDictionaryEntry *entry = av_dict_get(src, key, NULL, 0);
1199     if (entry)
1200         av_dict_set(dst, key, entry->value, AV_DICT_DONT_OVERWRITE);
1201     return 0;
1202 }
1203
1204 static int dash_init(AVFormatContext *s)
1205 {
1206     DASHContext *c = s->priv_data;
1207     int ret = 0, i;
1208     char *ptr;
1209     char basename[1024];
1210
1211     c->nr_of_streams_to_flush = 0;
1212     if (c->single_file_name)
1213         c->single_file = 1;
1214     if (c->single_file)
1215         c->use_template = 0;
1216
1217 #if FF_API_DASH_MIN_SEG_DURATION
1218     if (c->min_seg_duration != 5000000) {
1219         av_log(s, AV_LOG_WARNING, "The min_seg_duration option is deprecated and will be removed. Please use the -seg_duration\n");
1220         c->seg_duration = c->min_seg_duration;
1221     }
1222 #endif
1223     if (c->lhls && s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
1224         av_log(s, AV_LOG_ERROR,
1225                "LHLS is experimental, Please set -strict experimental in order to enable it.\n");
1226         return AVERROR_EXPERIMENTAL;
1227     }
1228
1229     if (c->lhls && !c->streaming) {
1230         av_log(s, AV_LOG_WARNING, "LHLS option will be ignored as streaming is not enabled\n");
1231         c->lhls = 0;
1232     }
1233
1234     if (c->lhls && !c->hls_playlist) {
1235         av_log(s, AV_LOG_WARNING, "LHLS option will be ignored as hls_playlist is not enabled\n");
1236         c->lhls = 0;
1237     }
1238
1239     if (c->global_sidx && !c->single_file) {
1240         av_log(s, AV_LOG_WARNING, "Global SIDX option will be ignored as single_file is not enabled\n");
1241         c->global_sidx = 0;
1242     }
1243
1244     if (c->global_sidx && c->streaming) {
1245         av_log(s, AV_LOG_WARNING, "Global SIDX option will be ignored as streaming is enabled\n");
1246         c->global_sidx = 0;
1247     }
1248     if (c->frag_type == FRAG_TYPE_NONE && c->streaming) {
1249         av_log(s, AV_LOG_VERBOSE, "Changing frag_type from none to every_frame as streaming is enabled\n");
1250         c->frag_type = FRAG_TYPE_EVERY_FRAME;
1251     }
1252
1253     av_strlcpy(c->dirname, s->url, sizeof(c->dirname));
1254     ptr = strrchr(c->dirname, '/');
1255     if (ptr) {
1256         av_strlcpy(basename, &ptr[1], sizeof(basename));
1257         ptr[1] = '\0';
1258     } else {
1259         c->dirname[0] = '\0';
1260         av_strlcpy(basename, s->url, sizeof(basename));
1261     }
1262
1263     ptr = strrchr(basename, '.');
1264     if (ptr)
1265         *ptr = '\0';
1266
1267     c->streams = av_mallocz(sizeof(*c->streams) * s->nb_streams);
1268     if (!c->streams)
1269         return AVERROR(ENOMEM);
1270
1271     if ((ret = parse_adaptation_sets(s)) < 0)
1272         return ret;
1273
1274     if ((ret = init_segment_types(s)) < 0)
1275         return ret;
1276
1277     for (i = 0; i < s->nb_streams; i++) {
1278         OutputStream *os = &c->streams[i];
1279         AdaptationSet *as = &c->as[os->as_idx - 1];
1280         AVFormatContext *ctx;
1281         AVStream *st;
1282         AVDictionary *opts = NULL;
1283         char filename[1024];
1284
1285         os->bit_rate = s->streams[i]->codecpar->bit_rate;
1286         if (!os->bit_rate) {
1287             int level = s->strict_std_compliance >= FF_COMPLIANCE_STRICT ?
1288                         AV_LOG_ERROR : AV_LOG_WARNING;
1289             av_log(s, level, "No bit rate set for stream %d\n", i);
1290             if (s->strict_std_compliance >= FF_COMPLIANCE_STRICT)
1291                 return AVERROR(EINVAL);
1292         }
1293
1294         // copy AdaptationSet language and role from stream metadata
1295         dict_copy_entry(&as->metadata, s->streams[i]->metadata, "language");
1296         dict_copy_entry(&as->metadata, s->streams[i]->metadata, "role");
1297
1298         if (c->init_seg_name) {
1299             os->init_seg_name = av_strireplace(c->init_seg_name, "$ext$", os->extension_name);
1300             if (!os->init_seg_name)
1301                 return AVERROR(ENOMEM);
1302         }
1303         if (c->media_seg_name) {
1304             os->media_seg_name = av_strireplace(c->media_seg_name, "$ext$", os->extension_name);
1305             if (!os->media_seg_name)
1306                 return AVERROR(ENOMEM);
1307         }
1308         if (c->single_file_name) {
1309             os->single_file_name = av_strireplace(c->single_file_name, "$ext$", os->extension_name);
1310             if (!os->single_file_name)
1311                 return AVERROR(ENOMEM);
1312         }
1313
1314         if (os->segment_type == SEGMENT_TYPE_WEBM) {
1315             if ((!c->single_file && check_file_extension(os->init_seg_name, os->format_name) != 0) ||
1316                 (!c->single_file && check_file_extension(os->media_seg_name, os->format_name) != 0) ||
1317                 (c->single_file && check_file_extension(os->single_file_name, os->format_name) != 0)) {
1318                 av_log(s, AV_LOG_WARNING,
1319                        "One or many segment file names doesn't end with .webm. "
1320                        "Override -init_seg_name and/or -media_seg_name and/or "
1321                        "-single_file_name to end with the extension .webm\n");
1322             }
1323             if (c->streaming) {
1324                 // Streaming not supported as matroskaenc buffers internally before writing the output
1325                 av_log(s, AV_LOG_WARNING, "One or more streams in WebM output format. Streaming option will be ignored\n");
1326                 c->streaming = 0;
1327             }
1328         }
1329
1330         os->ctx = ctx = avformat_alloc_context();
1331         if (!ctx)
1332             return AVERROR(ENOMEM);
1333
1334         ctx->oformat = av_guess_format(os->format_name, NULL, NULL);
1335         if (!ctx->oformat)
1336             return AVERROR_MUXER_NOT_FOUND;
1337         ctx->interrupt_callback    = s->interrupt_callback;
1338         ctx->opaque                = s->opaque;
1339         ctx->io_close              = s->io_close;
1340         ctx->io_open               = s->io_open;
1341         ctx->strict_std_compliance = s->strict_std_compliance;
1342
1343         if (!(st = avformat_new_stream(ctx, NULL)))
1344             return AVERROR(ENOMEM);
1345         avcodec_parameters_copy(st->codecpar, s->streams[i]->codecpar);
1346         st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio;
1347         st->time_base = s->streams[i]->time_base;
1348         st->avg_frame_rate = s->streams[i]->avg_frame_rate;
1349         ctx->avoid_negative_ts = s->avoid_negative_ts;
1350         ctx->flags = s->flags;
1351
1352         if (c->single_file) {
1353             if (os->single_file_name)
1354                 ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), os->single_file_name, i, 0, os->bit_rate, 0);
1355             else
1356                 snprintf(os->initfile, sizeof(os->initfile), "%s-stream%d.%s", basename, i, os->format_name);
1357         } else {
1358             ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), os->init_seg_name, i, 0, os->bit_rate, 0);
1359         }
1360         snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile);
1361         set_http_options(&opts, c);
1362         if (!c->single_file) {
1363             if ((ret = avio_open_dyn_buf(&ctx->pb)) < 0)
1364                 return ret;
1365             ret = s->io_open(s, &os->out, filename, AVIO_FLAG_WRITE, &opts);
1366         } else {
1367             ctx->url = av_strdup(filename);
1368             ret = avio_open2(&ctx->pb, filename, AVIO_FLAG_WRITE, NULL, &opts);
1369         }
1370         av_dict_free(&opts);
1371         if (ret < 0)
1372             return ret;
1373         os->init_start_pos = 0;
1374
1375         av_dict_copy(&opts, c->format_options, 0);
1376         if (!as->seg_duration)
1377             as->seg_duration = c->seg_duration;
1378         if (!as->frag_duration)
1379             as->frag_duration = c->frag_duration;
1380         if (as->frag_type < 0)
1381             as->frag_type = c->frag_type;
1382         os->seg_duration = as->seg_duration;
1383         os->frag_duration = as->frag_duration;
1384         os->frag_type = as->frag_type;
1385
1386         if (os->frag_type == FRAG_TYPE_DURATION && !os->frag_duration) {
1387             av_log(s, AV_LOG_WARNING, "frag_type set to duration for stream %d but no frag_duration set\n", i);
1388             os->frag_type = c->streaming ? FRAG_TYPE_EVERY_FRAME : FRAG_TYPE_NONE;
1389         }
1390         if (os->frag_type == FRAG_TYPE_DURATION && os->frag_duration > os->seg_duration) {
1391             av_log(s, AV_LOG_ERROR, "Fragment duration %"PRId64" is longer than Segment duration %"PRId64"\n", os->frag_duration, os->seg_duration);
1392             return AVERROR(EINVAL);
1393         }
1394
1395         if (os->segment_type == SEGMENT_TYPE_MP4) {
1396             if (c->streaming)
1397                 // skip_sidx : Reduce bitrate overhead
1398                 // skip_trailer : Avoids growing memory usage with time
1399                 av_dict_set(&opts, "movflags", "dash+delay_moov+skip_sidx+skip_trailer", 0);
1400             else {
1401                 if (c->global_sidx)
1402                     av_dict_set(&opts, "movflags", "dash+delay_moov+global_sidx+skip_trailer", 0);
1403                 else
1404                     av_dict_set(&opts, "movflags", "dash+delay_moov+skip_trailer", 0);
1405             }
1406             if (os->frag_type == FRAG_TYPE_EVERY_FRAME)
1407                 av_dict_set(&opts, "movflags", "+frag_every_frame", AV_DICT_APPEND);
1408             else
1409                 av_dict_set(&opts, "movflags", "+frag_custom", AV_DICT_APPEND);
1410             if (os->frag_type == FRAG_TYPE_DURATION)
1411                 av_dict_set_int(&opts, "frag_duration", os->frag_duration, 0);
1412         } else {
1413             av_dict_set_int(&opts, "cluster_time_limit", c->seg_duration / 1000, 0);
1414             av_dict_set_int(&opts, "cluster_size_limit", 5 * 1024 * 1024, 0); // set a large cluster size limit
1415             av_dict_set_int(&opts, "dash", 1, 0);
1416             av_dict_set_int(&opts, "dash_track_number", i + 1, 0);
1417             av_dict_set_int(&opts, "live", 1, 0);
1418         }
1419         ret = avformat_init_output(ctx, &opts);
1420         av_dict_free(&opts);
1421         if (ret < 0)
1422             return ret;
1423         os->ctx_inited = 1;
1424         avio_flush(ctx->pb);
1425
1426         av_log(s, AV_LOG_VERBOSE, "Representation %d init segment will be written to: %s\n", i, filename);
1427
1428         s->streams[i]->time_base = st->time_base;
1429         // If the muxer wants to shift timestamps, request to have them shifted
1430         // already before being handed to this muxer, so we don't have mismatches
1431         // between the MPD and the actual segments.
1432         s->avoid_negative_ts = ctx->avoid_negative_ts;
1433         if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
1434             AVRational avg_frame_rate = s->streams[i]->avg_frame_rate;
1435             if (avg_frame_rate.num > 0) {
1436                 if (av_cmp_q(avg_frame_rate, as->min_frame_rate) < 0)
1437                     as->min_frame_rate = avg_frame_rate;
1438                 if (av_cmp_q(as->max_frame_rate, avg_frame_rate) < 0)
1439                     as->max_frame_rate = avg_frame_rate;
1440             } else {
1441                 as->ambiguous_frame_rate = 1;
1442             }
1443             c->has_video = 1;
1444         }
1445
1446         set_codec_str(s, st->codecpar, &st->avg_frame_rate, os->codec_str,
1447                       sizeof(os->codec_str));
1448         os->first_pts = AV_NOPTS_VALUE;
1449         os->max_pts = AV_NOPTS_VALUE;
1450         os->last_dts = AV_NOPTS_VALUE;
1451         os->segment_index = 1;
1452
1453         if (s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
1454             c->nr_of_streams_to_flush++;
1455     }
1456
1457     if (!c->has_video && c->seg_duration <= 0) {
1458         av_log(s, AV_LOG_WARNING, "no video stream and no seg duration set\n");
1459         return AVERROR(EINVAL);
1460     }
1461
1462     c->nr_of_streams_flushed = 0;
1463
1464     return 0;
1465 }
1466
1467 static int dash_write_header(AVFormatContext *s)
1468 {
1469     DASHContext *c = s->priv_data;
1470     int i, ret;
1471     for (i = 0; i < s->nb_streams; i++) {
1472         OutputStream *os = &c->streams[i];
1473         if ((ret = avformat_write_header(os->ctx, NULL)) < 0)
1474             return ret;
1475
1476         // Flush init segment
1477         // Only for WebM segment, since for mp4 delay_moov is set and
1478         // the init segment is thus flushed after the first packets.
1479         if (os->segment_type == SEGMENT_TYPE_WEBM &&
1480             (ret = flush_init_segment(s, os)) < 0)
1481             return ret;
1482     }
1483     return ret;
1484 }
1485
1486 static int add_segment(OutputStream *os, const char *file,
1487                        int64_t time, int64_t duration,
1488                        int64_t start_pos, int64_t range_length,
1489                        int64_t index_length, int next_exp_index)
1490 {
1491     int err;
1492     Segment *seg;
1493     if (os->nb_segments >= os->segments_size) {
1494         os->segments_size = (os->segments_size + 1) * 2;
1495         if ((err = av_reallocp(&os->segments, sizeof(*os->segments) *
1496                                os->segments_size)) < 0) {
1497             os->segments_size = 0;
1498             os->nb_segments = 0;
1499             return err;
1500         }
1501     }
1502     seg = av_mallocz(sizeof(*seg));
1503     if (!seg)
1504         return AVERROR(ENOMEM);
1505     av_strlcpy(seg->file, file, sizeof(seg->file));
1506     seg->time = time;
1507     seg->duration = duration;
1508     if (seg->time < 0) { // If pts<0, it is expected to be cut away with an edit list
1509         seg->duration += seg->time;
1510         seg->time = 0;
1511     }
1512     seg->start_pos = start_pos;
1513     seg->range_length = range_length;
1514     seg->index_length = index_length;
1515     os->segments[os->nb_segments++] = seg;
1516     os->segment_index++;
1517     //correcting the segment index if it has fallen behind the expected value
1518     if (os->segment_index < next_exp_index) {
1519         av_log(NULL, AV_LOG_WARNING, "Correcting the segment index after file %s: current=%d corrected=%d\n",
1520                file, os->segment_index, next_exp_index);
1521         os->segment_index = next_exp_index;
1522     }
1523     return 0;
1524 }
1525
1526 static void write_styp(AVIOContext *pb)
1527 {
1528     avio_wb32(pb, 24);
1529     ffio_wfourcc(pb, "styp");
1530     ffio_wfourcc(pb, "msdh");
1531     avio_wb32(pb, 0); /* minor */
1532     ffio_wfourcc(pb, "msdh");
1533     ffio_wfourcc(pb, "msix");
1534 }
1535
1536 static void find_index_range(AVFormatContext *s, const char *full_path,
1537                              int64_t pos, int *index_length)
1538 {
1539     uint8_t buf[8];
1540     AVIOContext *pb;
1541     int ret;
1542
1543     ret = s->io_open(s, &pb, full_path, AVIO_FLAG_READ, NULL);
1544     if (ret < 0)
1545         return;
1546     if (avio_seek(pb, pos, SEEK_SET) != pos) {
1547         ff_format_io_close(s, &pb);
1548         return;
1549     }
1550     ret = avio_read(pb, buf, 8);
1551     ff_format_io_close(s, &pb);
1552     if (ret < 8)
1553         return;
1554     if (AV_RL32(&buf[4]) != MKTAG('s', 'i', 'd', 'x'))
1555         return;
1556     *index_length = AV_RB32(&buf[0]);
1557 }
1558
1559 static int update_stream_extradata(AVFormatContext *s, OutputStream *os,
1560                                    AVPacket *pkt, AVRational *frame_rate)
1561 {
1562     AVCodecParameters *par = os->ctx->streams[0]->codecpar;
1563     uint8_t *extradata;
1564     int ret, extradata_size;
1565
1566     if (par->extradata_size)
1567         return 0;
1568
1569     extradata = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &extradata_size);
1570     if (!extradata_size)
1571         return 0;
1572
1573     ret = ff_alloc_extradata(par, extradata_size);
1574     if (ret < 0)
1575         return ret;
1576
1577     memcpy(par->extradata, extradata, extradata_size);
1578
1579     set_codec_str(s, par, frame_rate, os->codec_str, sizeof(os->codec_str));
1580
1581     return 0;
1582 }
1583
1584 static void dashenc_delete_file(AVFormatContext *s, char *filename) {
1585     DASHContext *c = s->priv_data;
1586     int http_base_proto = ff_is_http_proto(filename);
1587
1588     if (http_base_proto) {
1589         AVIOContext *out = NULL;
1590         AVDictionary *http_opts = NULL;
1591
1592         set_http_options(&http_opts, c);
1593         av_dict_set(&http_opts, "method", "DELETE", 0);
1594
1595         if (dashenc_io_open(s, &out, filename, &http_opts) < 0) {
1596             av_log(s, AV_LOG_ERROR, "failed to delete %s\n", filename);
1597         }
1598
1599         av_dict_free(&http_opts);
1600         ff_format_io_close(s, &out);
1601     } else {
1602         int res = avpriv_io_delete(filename);
1603         if (res < 0) {
1604             char errbuf[AV_ERROR_MAX_STRING_SIZE];
1605             av_strerror(res, errbuf, sizeof(errbuf));
1606             av_log(s, (res == AVERROR(ENOENT) ? AV_LOG_WARNING : AV_LOG_ERROR), "failed to delete %s: %s\n", filename, errbuf);
1607         }
1608     }
1609 }
1610
1611 static int dashenc_delete_segment_file(AVFormatContext *s, const char* file)
1612 {
1613     DASHContext *c = s->priv_data;
1614     size_t dirname_len, file_len;
1615     char filename[1024];
1616
1617     dirname_len = strlen(c->dirname);
1618     if (dirname_len >= sizeof(filename)) {
1619         av_log(s, AV_LOG_WARNING, "Cannot delete segments as the directory path is too long: %"PRIu64" characters: %s\n",
1620             (uint64_t)dirname_len, c->dirname);
1621         return AVERROR(ENAMETOOLONG);
1622     }
1623
1624     memcpy(filename, c->dirname, dirname_len);
1625
1626     file_len = strlen(file);
1627     if ((dirname_len + file_len) >= sizeof(filename)) {
1628         av_log(s, AV_LOG_WARNING, "Cannot delete segments as the path is too long: %"PRIu64" characters: %s%s\n",
1629             (uint64_t)(dirname_len + file_len), c->dirname, file);
1630         return AVERROR(ENAMETOOLONG);
1631     }
1632
1633     memcpy(filename + dirname_len, file, file_len + 1); // include the terminating zero
1634     dashenc_delete_file(s, filename);
1635
1636     return 0;
1637 }
1638
1639 static inline void dashenc_delete_media_segments(AVFormatContext *s, OutputStream *os, int remove_count)
1640 {
1641     for (int i = 0; i < remove_count; ++i) {
1642         dashenc_delete_segment_file(s, os->segments[i]->file);
1643
1644         // Delete the segment regardless of whether the file was successfully deleted
1645         av_free(os->segments[i]);
1646     }
1647
1648     os->nb_segments -= remove_count;
1649     memmove(os->segments, os->segments + remove_count, os->nb_segments * sizeof(*os->segments));
1650 }
1651
1652 static int dash_flush(AVFormatContext *s, int final, int stream)
1653 {
1654     DASHContext *c = s->priv_data;
1655     int i, ret = 0;
1656
1657     const char *proto = avio_find_protocol_name(s->url);
1658     int use_rename = proto && !strcmp(proto, "file");
1659
1660     int cur_flush_segment_index = 0, next_exp_index = -1;
1661     if (stream >= 0) {
1662         cur_flush_segment_index = c->streams[stream].segment_index;
1663
1664         //finding the next segment's expected index, based on the current pts value
1665         if (c->use_template && !c->use_timeline && c->index_correction &&
1666             c->streams[stream].last_pts != AV_NOPTS_VALUE &&
1667             c->streams[stream].first_pts != AV_NOPTS_VALUE) {
1668             int64_t pts_diff = av_rescale_q(c->streams[stream].last_pts -
1669                                             c->streams[stream].first_pts,
1670                                             s->streams[stream]->time_base,
1671                                             AV_TIME_BASE_Q);
1672             next_exp_index = (pts_diff / c->streams[stream].seg_duration) + 1;
1673         }
1674     }
1675
1676     for (i = 0; i < s->nb_streams; i++) {
1677         OutputStream *os = &c->streams[i];
1678         AVStream *st = s->streams[i];
1679         int range_length, index_length = 0;
1680
1681         if (!os->packets_written)
1682             continue;
1683
1684         // Flush the single stream that got a keyframe right now.
1685         // Flush all audio streams as well, in sync with video keyframes,
1686         // but not the other video streams.
1687         if (stream >= 0 && i != stream) {
1688             if (s->streams[stream]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO &&
1689                 s->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)
1690                 continue;
1691             if (s->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
1692                 continue;
1693             // Make sure we don't flush audio streams multiple times, when
1694             // all video streams are flushed one at a time.
1695             if (c->has_video && os->segment_index > cur_flush_segment_index)
1696                 continue;
1697         }
1698
1699         if (!c->single_file) {
1700             if (os->segment_type == SEGMENT_TYPE_MP4 && !os->written_len)
1701                 write_styp(os->ctx->pb);
1702         } else {
1703             snprintf(os->full_path, sizeof(os->full_path), "%s%s", c->dirname, os->initfile);
1704         }
1705
1706         ret = flush_dynbuf(c, os, &range_length);
1707         if (ret < 0)
1708             break;
1709         os->packets_written = 0;
1710
1711         if (c->single_file) {
1712             find_index_range(s, os->full_path, os->pos, &index_length);
1713         } else {
1714             dashenc_io_close(s, &os->out, os->temp_path);
1715
1716             if (use_rename) {
1717                 ret = avpriv_io_move(os->temp_path, os->full_path);
1718                 if (ret < 0)
1719                     break;
1720             }
1721         }
1722
1723         os->last_duration = FFMAX(os->last_duration, av_rescale_q(os->max_pts - os->start_pts,
1724                                                                   st->time_base,
1725                                                                   AV_TIME_BASE_Q));
1726
1727         if (!os->muxer_overhead)
1728             os->muxer_overhead = ((int64_t) (range_length - os->total_pkt_size) *
1729                                   8 * AV_TIME_BASE) /
1730                                  av_rescale_q(os->max_pts - os->start_pts,
1731                                               st->time_base, AV_TIME_BASE_Q);
1732         os->total_pkt_size = 0;
1733
1734         if (!os->bit_rate) {
1735             // calculate average bitrate of first segment
1736             int64_t bitrate = (int64_t) range_length * 8 * AV_TIME_BASE / av_rescale_q(os->max_pts - os->start_pts,
1737                                                                                        st->time_base,
1738                                                                                        AV_TIME_BASE_Q);
1739             if (bitrate >= 0)
1740                 os->bit_rate = bitrate;
1741         }
1742         add_segment(os, os->filename, os->start_pts, os->max_pts - os->start_pts, os->pos, range_length, index_length, next_exp_index);
1743         av_log(s, AV_LOG_VERBOSE, "Representation %d media segment %d written to: %s\n", i, os->segment_index, os->full_path);
1744
1745         os->pos += range_length;
1746     }
1747
1748     if (c->window_size) {
1749         for (i = 0; i < s->nb_streams; i++) {
1750             OutputStream *os = &c->streams[i];
1751             int remove_count = os->nb_segments - c->window_size - c->extra_window_size;
1752             if (remove_count > 0)
1753                 dashenc_delete_media_segments(s, os, remove_count);
1754         }
1755     }
1756
1757     if (final) {
1758         for (i = 0; i < s->nb_streams; i++) {
1759             OutputStream *os = &c->streams[i];
1760             if (os->ctx && os->ctx_inited) {
1761                 int64_t file_size = avio_tell(os->ctx->pb);
1762                 av_write_trailer(os->ctx);
1763                 if (c->global_sidx) {
1764                     int j, start_index, start_number;
1765                     int64_t sidx_size = avio_tell(os->ctx->pb) - file_size;
1766                     get_start_index_number(os, c, &start_index, &start_number);
1767                     if (start_index >= os->nb_segments ||
1768                         os->segment_type != SEGMENT_TYPE_MP4)
1769                         continue;
1770                     os->init_range_length += sidx_size;
1771                     for (j = start_index; j < os->nb_segments; j++) {
1772                         Segment *seg = os->segments[j];
1773                         seg->start_pos += sidx_size;
1774                     }
1775                 }
1776
1777             }
1778         }
1779     }
1780     if (ret >= 0) {
1781         if (c->has_video && !final) {
1782             c->nr_of_streams_flushed++;
1783             if (c->nr_of_streams_flushed != c->nr_of_streams_to_flush)
1784                 return ret;
1785
1786             c->nr_of_streams_flushed = 0;
1787         }
1788         ret = write_manifest(s, final);
1789     }
1790     return ret;
1791 }
1792
1793 static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
1794 {
1795     DASHContext *c = s->priv_data;
1796     AVStream *st = s->streams[pkt->stream_index];
1797     OutputStream *os = &c->streams[pkt->stream_index];
1798     int64_t seg_end_duration, elapsed_duration;
1799     int ret;
1800
1801     ret = update_stream_extradata(s, os, pkt, &st->avg_frame_rate);
1802     if (ret < 0)
1803         return ret;
1804
1805     // Fill in a heuristic guess of the packet duration, if none is available.
1806     // The mp4 muxer will do something similar (for the last packet in a fragment)
1807     // if nothing is set (setting it for the other packets doesn't hurt).
1808     // By setting a nonzero duration here, we can be sure that the mp4 muxer won't
1809     // invoke its heuristic (this doesn't have to be identical to that algorithm),
1810     // so that we know the exact timestamps of fragments.
1811     if (!pkt->duration && os->last_dts != AV_NOPTS_VALUE)
1812         pkt->duration = pkt->dts - os->last_dts;
1813     os->last_dts = pkt->dts;
1814
1815     // If forcing the stream to start at 0, the mp4 muxer will set the start
1816     // timestamps to 0. Do the same here, to avoid mismatches in duration/timestamps.
1817     if (os->first_pts == AV_NOPTS_VALUE &&
1818         s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO) {
1819         pkt->pts -= pkt->dts;
1820         pkt->dts  = 0;
1821     }
1822
1823     if (os->first_pts == AV_NOPTS_VALUE)
1824         os->first_pts = pkt->pts;
1825     os->last_pts = pkt->pts;
1826
1827     if (!c->availability_start_time[0]) {
1828         int64_t start_time_us = av_gettime();
1829         c->start_time_s = start_time_us / 1000000;
1830         format_date_now(c->availability_start_time,
1831                         sizeof(c->availability_start_time));
1832     }
1833
1834     if (!os->availability_time_offset &&
1835         ((os->frag_type == FRAG_TYPE_DURATION && os->seg_duration != os->frag_duration) ||
1836          (os->frag_type == FRAG_TYPE_EVERY_FRAME && pkt->duration))) {
1837         int64_t frame_duration = 0;
1838
1839         switch (os->frag_type) {
1840         case FRAG_TYPE_DURATION:
1841             frame_duration = os->frag_duration;
1842             break;
1843         case FRAG_TYPE_EVERY_FRAME:
1844             frame_duration = av_rescale_q(pkt->duration, st->time_base, AV_TIME_BASE_Q);
1845             break;
1846         }
1847
1848          os->availability_time_offset = ((double) os->seg_duration -
1849                                          frame_duration) / AV_TIME_BASE;
1850     }
1851
1852     if (c->use_template && !c->use_timeline) {
1853         elapsed_duration = pkt->pts - os->first_pts;
1854         seg_end_duration = (int64_t) os->segment_index * os->seg_duration;
1855     } else {
1856         elapsed_duration = pkt->pts - os->start_pts;
1857         seg_end_duration = os->seg_duration;
1858     }
1859
1860     if (pkt->flags & AV_PKT_FLAG_KEY && os->packets_written &&
1861         av_compare_ts(elapsed_duration, st->time_base,
1862                       seg_end_duration, AV_TIME_BASE_Q) >= 0) {
1863         if (!c->has_video || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
1864         c->last_duration = av_rescale_q(pkt->pts - os->start_pts,
1865                                         st->time_base,
1866                                         AV_TIME_BASE_Q);
1867         c->total_duration = av_rescale_q(pkt->pts - os->first_pts,
1868                                          st->time_base,
1869                                          AV_TIME_BASE_Q);
1870
1871         if ((!c->use_timeline || !c->use_template) && os->last_duration) {
1872             if (c->last_duration < os->last_duration*9/10 ||
1873                 c->last_duration > os->last_duration*11/10) {
1874                 av_log(s, AV_LOG_WARNING,
1875                        "Segment durations differ too much, enable use_timeline "
1876                        "and use_template, or keep a stricter keyframe interval\n");
1877             }
1878         }
1879         }
1880
1881         if ((ret = dash_flush(s, 0, pkt->stream_index)) < 0)
1882             return ret;
1883     }
1884
1885     if (!os->packets_written) {
1886         // If we wrote a previous segment, adjust the start time of the segment
1887         // to the end of the previous one (which is the same as the mp4 muxer
1888         // does). This avoids gaps in the timeline.
1889         if (os->max_pts != AV_NOPTS_VALUE)
1890             os->start_pts = os->max_pts;
1891         else
1892             os->start_pts = pkt->pts;
1893     }
1894     if (os->max_pts == AV_NOPTS_VALUE)
1895         os->max_pts = pkt->pts + pkt->duration;
1896     else
1897         os->max_pts = FFMAX(os->max_pts, pkt->pts + pkt->duration);
1898     os->packets_written++;
1899     os->total_pkt_size += pkt->size;
1900     if ((ret = ff_write_chained(os->ctx, 0, pkt, s, 0)) < 0)
1901         return ret;
1902
1903     if (!os->init_range_length)
1904         flush_init_segment(s, os);
1905
1906     //open the output context when the first frame of a segment is ready
1907     if (!c->single_file && os->packets_written == 1) {
1908         AVDictionary *opts = NULL;
1909         const char *proto = avio_find_protocol_name(s->url);
1910         int use_rename = proto && !strcmp(proto, "file");
1911         os->filename[0] = os->full_path[0] = os->temp_path[0] = '\0';
1912         ff_dash_fill_tmpl_params(os->filename, sizeof(os->filename),
1913                                  os->media_seg_name, pkt->stream_index,
1914                                  os->segment_index, os->bit_rate, os->start_pts);
1915         snprintf(os->full_path, sizeof(os->full_path), "%s%s", c->dirname,
1916                  os->filename);
1917         snprintf(os->temp_path, sizeof(os->temp_path),
1918                  use_rename ? "%s.tmp" : "%s", os->full_path);
1919         set_http_options(&opts, c);
1920         ret = dashenc_io_open(s, &os->out, os->temp_path, &opts);
1921         av_dict_free(&opts);
1922         if (ret < 0) {
1923             return handle_io_open_error(s, ret, os->temp_path);
1924         }
1925         if (c->lhls) {
1926             char *prefetch_url = use_rename ? NULL : os->filename;
1927             write_hls_media_playlist(os, s, pkt->stream_index, 0, prefetch_url);
1928         }
1929     }
1930
1931     //write out the data immediately in streaming mode
1932     if (c->streaming && os->segment_type == SEGMENT_TYPE_MP4) {
1933         int len = 0;
1934         uint8_t *buf = NULL;
1935         if (!os->written_len)
1936             write_styp(os->ctx->pb);
1937         avio_flush(os->ctx->pb);
1938         len = avio_get_dyn_buf (os->ctx->pb, &buf);
1939         if (os->out) {
1940             avio_write(os->out, buf + os->written_len, len - os->written_len);
1941             avio_flush(os->out);
1942         }
1943         os->written_len = len;
1944     }
1945
1946     return ret;
1947 }
1948
1949 static int dash_write_trailer(AVFormatContext *s)
1950 {
1951     DASHContext *c = s->priv_data;
1952     int i;
1953
1954     if (s->nb_streams > 0) {
1955         OutputStream *os = &c->streams[0];
1956         // If no segments have been written so far, try to do a crude
1957         // guess of the segment duration
1958         if (!c->last_duration)
1959             c->last_duration = av_rescale_q(os->max_pts - os->start_pts,
1960                                             s->streams[0]->time_base,
1961                                             AV_TIME_BASE_Q);
1962         c->total_duration = av_rescale_q(os->max_pts - os->first_pts,
1963                                          s->streams[0]->time_base,
1964                                          AV_TIME_BASE_Q);
1965     }
1966     dash_flush(s, 1, -1);
1967
1968     if (c->remove_at_exit) {
1969         for (i = 0; i < s->nb_streams; ++i) {
1970             OutputStream *os = &c->streams[i];
1971             dashenc_delete_media_segments(s, os, os->nb_segments);
1972             dashenc_delete_segment_file(s, os->initfile);
1973             if (c->hls_playlist && os->segment_type == SEGMENT_TYPE_MP4) {
1974                 char filename[1024];
1975                 get_hls_playlist_name(filename, sizeof(filename), c->dirname, i);
1976                 dashenc_delete_file(s, filename);
1977             }
1978         }
1979         dashenc_delete_file(s, s->url);
1980
1981         if (c->hls_playlist && c->master_playlist_created) {
1982             char filename[1024];
1983             snprintf(filename, sizeof(filename), "%smaster.m3u8", c->dirname);
1984             dashenc_delete_file(s, filename);
1985         }
1986     }
1987
1988     return 0;
1989 }
1990
1991 static int dash_check_bitstream(struct AVFormatContext *s, const AVPacket *avpkt)
1992 {
1993     DASHContext *c = s->priv_data;
1994     OutputStream *os = &c->streams[avpkt->stream_index];
1995     AVFormatContext *oc = os->ctx;
1996     if (oc->oformat->check_bitstream) {
1997         int ret;
1998         AVPacket pkt = *avpkt;
1999         pkt.stream_index = 0;
2000         ret = oc->oformat->check_bitstream(oc, &pkt);
2001         if (ret == 1) {
2002             AVStream *st = s->streams[avpkt->stream_index];
2003             AVStream *ost = oc->streams[0];
2004             st->internal->bsfcs = ost->internal->bsfcs;
2005             st->internal->nb_bsfcs = ost->internal->nb_bsfcs;
2006             ost->internal->bsfcs = NULL;
2007             ost->internal->nb_bsfcs = 0;
2008         }
2009         return ret;
2010     }
2011     return 1;
2012 }
2013
2014 #define OFFSET(x) offsetof(DASHContext, x)
2015 #define E AV_OPT_FLAG_ENCODING_PARAM
2016 static const AVOption options[] = {
2017     { "adaptation_sets", "Adaptation sets. Syntax: id=0,streams=0,1,2 id=1,streams=3,4 and so on", OFFSET(adaptation_sets), AV_OPT_TYPE_STRING, { 0 }, 0, 0, AV_OPT_FLAG_ENCODING_PARAM },
2018     { "window_size", "number of segments kept in the manifest", OFFSET(window_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, E },
2019     { "extra_window_size", "number of segments kept outside of the manifest before removing from disk", OFFSET(extra_window_size), AV_OPT_TYPE_INT, { .i64 = 5 }, 0, INT_MAX, E },
2020 #if FF_API_DASH_MIN_SEG_DURATION
2021     { "min_seg_duration", "minimum segment duration (in microseconds) (will be deprecated)", OFFSET(min_seg_duration), AV_OPT_TYPE_INT, { .i64 = 5000000 }, 0, INT_MAX, E },
2022 #endif
2023     { "seg_duration", "segment duration (in seconds, fractional value can be set)", OFFSET(seg_duration), AV_OPT_TYPE_DURATION, { .i64 = 5000000 }, 0, INT_MAX, E },
2024     { "frag_duration", "fragment duration (in seconds, fractional value can be set)", OFFSET(frag_duration), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT_MAX, E },
2025     { "frag_type", "set type of interval for fragments", OFFSET(frag_type), AV_OPT_TYPE_INT, {.i64 = FRAG_TYPE_NONE }, 0, FRAG_TYPE_NB - 1, E, "frag_type"},
2026     { "none", "one fragment per segment", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_NONE }, 0, UINT_MAX, E, "frag_type"},
2027     { "every_frame", "fragment at every frame", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_EVERY_FRAME }, 0, UINT_MAX, E, "frag_type"},
2028     { "duration", "fragment at specific time intervals", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_DURATION }, 0, UINT_MAX, E, "frag_type"},
2029     { "remove_at_exit", "remove all segments when finished", OFFSET(remove_at_exit), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
2030     { "use_template", "Use SegmentTemplate instead of SegmentList", OFFSET(use_template), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },
2031     { "use_timeline", "Use SegmentTimeline in SegmentTemplate", OFFSET(use_timeline), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },
2032     { "single_file", "Store all segments in one file, accessed using byte ranges", OFFSET(single_file), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
2033     { "single_file_name", "DASH-templated name to be used for baseURL. Implies storing all segments in one file, accessed using byte ranges", OFFSET(single_file_name), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E },
2034     { "init_seg_name", "DASH-templated name to used for the initialization segment", OFFSET(init_seg_name), AV_OPT_TYPE_STRING, {.str = "init-stream$RepresentationID$.$ext$"}, 0, 0, E },
2035     { "media_seg_name", "DASH-templated name to used for the media segments", OFFSET(media_seg_name), AV_OPT_TYPE_STRING, {.str = "chunk-stream$RepresentationID$-$Number%05d$.$ext$"}, 0, 0, E },
2036     { "utc_timing_url", "URL of the page that will return the UTC timestamp in ISO format", OFFSET(utc_timing_url), AV_OPT_TYPE_STRING, { 0 }, 0, 0, E },
2037     { "method", "set the HTTP method", OFFSET(method), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
2038     { "http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
2039     { "http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
2040     { "hls_playlist", "Generate HLS playlist files(master.m3u8, media_%d.m3u8)", OFFSET(hls_playlist), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
2041     { "streaming", "Enable/Disable streaming mode of output. Each frame will be moof fragment", OFFSET(streaming), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
2042     { "timeout", "set timeout for socket I/O operations", OFFSET(timeout), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT_MAX, .flags = E },
2043     { "index_correction", "Enable/Disable segment index correction logic", OFFSET(index_correction), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
2044     { "format_options","set list of options for the container format (mp4/webm) used for dash", OFFSET(format_options), AV_OPT_TYPE_DICT, {.str = NULL},  0, 0, E},
2045     { "global_sidx", "Write global SIDX atom. Applicable only for single file, mp4 output, non-streaming mode", OFFSET(global_sidx), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
2046     { "dash_segment_type", "set dash segment files type", OFFSET(segment_type_option), AV_OPT_TYPE_INT, {.i64 = SEGMENT_TYPE_AUTO }, 0, SEGMENT_TYPE_NB - 1, E, "segment_type"},
2047     { "auto", "select segment file format based on codec", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_AUTO }, 0, UINT_MAX,   E, "segment_type"},
2048     { "mp4", "make segment file in ISOBMFF format", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_MP4 }, 0, UINT_MAX,   E, "segment_type"},
2049     { "webm", "make segment file in WebM format", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_WEBM }, 0, UINT_MAX,   E, "segment_type"},
2050     { "ignore_io_errors", "Ignore IO errors during open and write. Useful for long-duration runs with network output", OFFSET(ignore_io_errors), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
2051     { "lhls", "Enable Low-latency HLS(Experimental). Adds #EXT-X-PREFETCH tag with current segment's URI", OFFSET(lhls), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
2052     { "master_m3u8_publish_rate", "Publish master playlist every after this many segment intervals", OFFSET(master_publish_rate), AV_OPT_TYPE_INT, {.i64 = 0}, 0, UINT_MAX, E},
2053     { NULL },
2054 };
2055
2056 static const AVClass dash_class = {
2057     .class_name = "dash muxer",
2058     .item_name  = av_default_item_name,
2059     .option     = options,
2060     .version    = LIBAVUTIL_VERSION_INT,
2061 };
2062
2063 AVOutputFormat ff_dash_muxer = {
2064     .name           = "dash",
2065     .long_name      = NULL_IF_CONFIG_SMALL("DASH Muxer"),
2066     .extensions     = "mpd",
2067     .priv_data_size = sizeof(DASHContext),
2068     .audio_codec    = AV_CODEC_ID_AAC,
2069     .video_codec    = AV_CODEC_ID_H264,
2070     .flags          = AVFMT_GLOBALHEADER | AVFMT_NOFILE | AVFMT_TS_NEGATIVE,
2071     .init           = dash_init,
2072     .write_header   = dash_write_header,
2073     .write_packet   = dash_write_packet,
2074     .write_trailer  = dash_write_trailer,
2075     .deinit         = dash_free,
2076     .check_bitstream = dash_check_bitstream,
2077     .priv_class     = &dash_class,
2078 };