FFmpeg
dashenc.c
Go to the documentation of this file.
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/rational.h"
35 #include "libavutil/time.h"
37 
38 #include "av1.h"
39 #include "avc.h"
40 #include "avformat.h"
41 #include "avio_internal.h"
42 #include "hlsplaylist.h"
43 #if CONFIG_HTTP_PROTOCOL
44 #include "http.h"
45 #endif
46 #include "internal.h"
47 #include "isom.h"
48 #include "os_support.h"
49 #include "url.h"
50 #include "vpcc.h"
51 #include "dash.h"
52 
53 typedef enum {
58 } SegmentType;
59 
60 typedef struct Segment {
61  char file[1024];
62  int64_t start_pos;
64  int64_t time;
66  int64_t duration;
67  int n;
68 } Segment;
69 
70 typedef struct AdaptationSet {
71  char id[10];
77 
78 typedef struct OutputStream {
83  char initfile[1024];
84  int64_t init_start_pos, pos;
89  int64_t last_dts, last_pts;
90  int bit_rate;
91  SegmentType segment_type; /* segment type selected for this particular stream */
92  const char *format_name;
93  const char *extension_name;
94  const char *single_file_name; /* file names selected for this particular stream */
95  const char *init_seg_name;
96  const char *media_seg_name;
97 
98  char codec_str[100];
100  char filename[1024];
101  char full_path[1024];
102  char temp_path[1024];
106 } OutputStream;
107 
108 typedef struct DASHContext {
109  const AVClass *class; /* Class for private options. */
112  int nb_as;
115 #if FF_API_DASH_MIN_SEG_DURATION
116  int min_seg_duration;
117 #endif
118  int64_t seg_duration;
125  int64_t last_duration;
126  int64_t total_duration;
128  time_t start_time_s;
129  char dirname[1024];
130  const char *single_file_name; /* file names as specified in options */
131  const char *init_seg_name;
132  const char *media_seg_name;
133  const char *utc_timing_url;
134  const char *method;
135  const char *user_agent;
142  int64_t timeout;
146  SegmentType segment_type_option; /* segment type as specified in options */
148  int lhls;
152 } DASHContext;
153 
154 static struct codec_string {
155  int id;
156  const char *str;
157 } codecs[] = {
158  { AV_CODEC_ID_VP8, "vp8" },
159  { AV_CODEC_ID_VP9, "vp9" },
160  { AV_CODEC_ID_VORBIS, "vorbis" },
161  { AV_CODEC_ID_OPUS, "opus" },
162  { AV_CODEC_ID_FLAC, "flac" },
163  { 0, NULL }
164 };
165 
166 static struct format_string {
168  const char *str;
169 } formats[] = {
170  { SEGMENT_TYPE_AUTO, "auto" },
171  { SEGMENT_TYPE_MP4, "mp4" },
172  { SEGMENT_TYPE_WEBM, "webm" },
173  { 0, NULL }
174 };
175 
176 static int dashenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename,
177  AVDictionary **options) {
178  DASHContext *c = s->priv_data;
179  int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
180  int err = AVERROR_MUXER_NOT_FOUND;
181  if (!*pb || !http_base_proto || !c->http_persistent) {
182  err = s->io_open(s, pb, filename, AVIO_FLAG_WRITE, options);
183 #if CONFIG_HTTP_PROTOCOL
184  } else {
185  URLContext *http_url_context = ffio_geturlcontext(*pb);
186  av_assert0(http_url_context);
187  err = ff_http_do_new_request(http_url_context, filename);
188  if (err < 0)
189  ff_format_io_close(s, pb);
190 #endif
191  }
192  return err;
193 }
194 
195 static void dashenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename) {
196  DASHContext *c = s->priv_data;
197  int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
198 
199  if (!*pb)
200  return;
201 
202  if (!http_base_proto || !c->http_persistent) {
203  ff_format_io_close(s, pb);
204 #if CONFIG_HTTP_PROTOCOL
205  } else {
206  URLContext *http_url_context = ffio_geturlcontext(*pb);
207  av_assert0(http_url_context);
208  avio_flush(*pb);
209  ffurl_shutdown(http_url_context, AVIO_FLAG_WRITE);
210 #endif
211  }
212 }
213 
214 static const char *get_format_str(SegmentType segment_type) {
215  int i;
216  for (i = 0; i < SEGMENT_TYPE_NB; i++)
217  if (formats[i].segment_type == segment_type)
218  return formats[i].str;
219  return NULL;
220 }
221 
222 static const char *get_extension_str(SegmentType type, int single_file)
223 {
224  switch (type) {
225 
226  case SEGMENT_TYPE_MP4: return single_file ? "mp4" : "m4s";
227  case SEGMENT_TYPE_WEBM: return "webm";
228  default: return NULL;
229  }
230 }
231 
232 static int handle_io_open_error(AVFormatContext *s, int err, char *url) {
233  DASHContext *c = s->priv_data;
234  char errbuf[AV_ERROR_MAX_STRING_SIZE];
235  av_strerror(err, errbuf, sizeof(errbuf));
236  av_log(s, c->ignore_io_errors ? AV_LOG_WARNING : AV_LOG_ERROR,
237  "Unable to open %s for writing: %s\n", url, errbuf);
238  return c->ignore_io_errors ? 0 : err;
239 }
240 
242 {
243  if (segment_type == SEGMENT_TYPE_AUTO) {
246  segment_type = SEGMENT_TYPE_WEBM;
247  } else {
248  segment_type = SEGMENT_TYPE_MP4;
249  }
250  }
251 
252  return segment_type;
253 }
254 
256 {
257  DASHContext *c = s->priv_data;
258  int has_mp4_streams = 0;
259  for (int i = 0; i < s->nb_streams; ++i) {
260  OutputStream *os = &c->streams[i];
261  SegmentType segment_type = select_segment_type(
262  c->segment_type_option, s->streams[i]->codecpar->codec_id);
263  os->segment_type = segment_type;
264  os->format_name = get_format_str(segment_type);
265  if (!os->format_name) {
266  av_log(s, AV_LOG_ERROR, "Could not select DASH segment type for stream %d\n", i);
268  }
269  os->extension_name = get_extension_str(segment_type, c->single_file);
270  if (!os->extension_name) {
271  av_log(s, AV_LOG_ERROR, "Could not get extension type for stream %d\n", i);
273  }
274 
275  has_mp4_streams |= segment_type == SEGMENT_TYPE_MP4;
276  }
277 
278  if (c->hls_playlist && !has_mp4_streams) {
279  av_log(s, AV_LOG_WARNING, "No mp4 streams, disabling HLS manifest generation\n");
280  c->hls_playlist = 0;
281  }
282 
283  return 0;
284 }
285 
286 static int check_file_extension(const char *filename, const char *extension) {
287  char *dot;
288  if (!filename || !extension)
289  return -1;
290  dot = strrchr(filename, '.');
291  if (dot && !strcmp(dot + 1, extension))
292  return 0;
293  return -1;
294 }
295 
297  AVRational *frame_rate, char *str, int size) {
298  VPCC vpcc;
299  int ret = ff_isom_get_vpcc_features(s, par, frame_rate, &vpcc);
300  if (ret == 0) {
301  av_strlcatf(str, size, "vp09.%02d.%02d.%02d",
302  vpcc.profile, vpcc.level, vpcc.bitdepth);
303  } else {
304  // Default to just vp9 in case of error while finding out profile or level
305  av_log(s, AV_LOG_WARNING, "Could not find VP9 profile and/or level\n");
306  av_strlcpy(str, "vp9", size);
307  }
308  return;
309 }
310 
312  AVRational *frame_rate, char *str, int size)
313 {
314  const AVCodecTag *tags[2] = { NULL, NULL };
315  uint32_t tag;
316  int i;
317 
318  // common Webm codecs are not part of RFC 6381
319  for (i = 0; codecs[i].id; i++)
320  if (codecs[i].id == par->codec_id) {
321  if (codecs[i].id == AV_CODEC_ID_VP9) {
322  set_vp9_codec_str(s, par, frame_rate, str, size);
323  } else {
324  av_strlcpy(str, codecs[i].str, size);
325  }
326  return;
327  }
328 
329  // for codecs part of RFC 6381
330  if (par->codec_type == AVMEDIA_TYPE_VIDEO)
331  tags[0] = ff_codec_movvideo_tags;
332  else if (par->codec_type == AVMEDIA_TYPE_AUDIO)
333  tags[0] = ff_codec_movaudio_tags;
334  else
335  return;
336 
337  tag = par->codec_tag;
338  if (!tag)
339  tag = av_codec_get_tag(tags, par->codec_id);
340  if (!tag)
341  return;
342  if (size < 5)
343  return;
344 
345  AV_WL32(str, tag);
346  str[4] = '\0';
347  if (!strcmp(str, "mp4a") || !strcmp(str, "mp4v")) {
348  uint32_t oti;
349  tags[0] = ff_mp4_obj_type;
350  oti = av_codec_get_tag(tags, par->codec_id);
351  if (oti)
352  av_strlcatf(str, size, ".%02"PRIx32, oti);
353  else
354  return;
355 
356  if (tag == MKTAG('m', 'p', '4', 'a')) {
357  if (par->extradata_size >= 2) {
358  int aot = par->extradata[0] >> 3;
359  if (aot == 31)
360  aot = ((AV_RB16(par->extradata) >> 5) & 0x3f) + 32;
361  av_strlcatf(str, size, ".%d", aot);
362  }
363  } else if (tag == MKTAG('m', 'p', '4', 'v')) {
364  // Unimplemented, should output ProfileLevelIndication as a decimal number
365  av_log(s, AV_LOG_WARNING, "Incomplete RFC 6381 codec string for mp4v\n");
366  }
367  } else if (!strcmp(str, "avc1")) {
368  uint8_t *tmpbuf = NULL;
369  uint8_t *extradata = par->extradata;
370  int extradata_size = par->extradata_size;
371  if (!extradata_size)
372  return;
373  if (extradata[0] != 1) {
374  AVIOContext *pb;
375  if (avio_open_dyn_buf(&pb) < 0)
376  return;
377  if (ff_isom_write_avcc(pb, extradata, extradata_size) < 0) {
378  ffio_free_dyn_buf(&pb);
379  return;
380  }
381  extradata_size = avio_close_dyn_buf(pb, &extradata);
382  tmpbuf = extradata;
383  }
384 
385  if (extradata_size >= 4)
386  av_strlcatf(str, size, ".%02x%02x%02x",
387  extradata[1], extradata[2], extradata[3]);
388  av_free(tmpbuf);
389  } else if (!strcmp(str, "av01")) {
391  if (!par->extradata_size)
392  return;
393  if (ff_av1_parse_seq_header(&seq, par->extradata, par->extradata_size) < 0)
394  return;
395 
396  av_strlcatf(str, size, ".%01u.%02u%s.%02u",
397  seq.profile, seq.level, seq.tier ? "H" : "M", seq.bitdepth);
399  av_strlcatf(str, size, ".%01u.%01u%01u%01u.%02u.%02u.%02u.%01u",
400  seq.monochrome,
403  seq.color_range);
404  }
405 }
406 
407 static int flush_dynbuf(DASHContext *c, OutputStream *os, int *range_length)
408 {
409  uint8_t *buffer;
410 
411  if (!os->ctx->pb) {
412  return AVERROR(EINVAL);
413  }
414 
415  // flush
416  av_write_frame(os->ctx, NULL);
417  avio_flush(os->ctx->pb);
418 
419  if (!c->single_file) {
420  // write out to file
421  *range_length = avio_close_dyn_buf(os->ctx->pb, &buffer);
422  os->ctx->pb = NULL;
423  if (os->out)
424  avio_write(os->out, buffer + os->written_len, *range_length - os->written_len);
425  os->written_len = 0;
426  av_free(buffer);
427 
428  // re-open buffer
429  return avio_open_dyn_buf(&os->ctx->pb);
430  } else {
431  *range_length = avio_tell(os->ctx->pb) - os->pos;
432  return 0;
433  }
434 }
435 
437 {
438  if (c->method)
439  av_dict_set(options, "method", c->method, 0);
440  if (c->user_agent)
441  av_dict_set(options, "user_agent", c->user_agent, 0);
442  if (c->http_persistent)
443  av_dict_set_int(options, "multiple_requests", 1, 0);
444  if (c->timeout >= 0)
445  av_dict_set_int(options, "timeout", c->timeout, 0);
446 }
447 
448 static void get_hls_playlist_name(char *playlist_name, int string_size,
449  const char *base_url, int id) {
450  if (base_url)
451  snprintf(playlist_name, string_size, "%smedia_%d.m3u8", base_url, id);
452  else
453  snprintf(playlist_name, string_size, "media_%d.m3u8", id);
454 }
455 
457  int *start_index, int *start_number) {
458  *start_index = 0;
459  *start_number = 1;
460  if (c->window_size) {
461  *start_index = FFMAX(os->nb_segments - c->window_size, 0);
462  *start_number = FFMAX(os->segment_index - c->window_size, 1);
463  }
464 }
465 
467  int representation_id, int final,
468  char *prefetch_url) {
469  DASHContext *c = s->priv_data;
470  int timescale = os->ctx->streams[0]->time_base.den;
471  char temp_filename_hls[1024];
472  char filename_hls[1024];
473  AVDictionary *http_opts = NULL;
474  int target_duration = 0;
475  int ret = 0;
476  const char *proto = avio_find_protocol_name(c->dirname);
477  int use_rename = proto && !strcmp(proto, "file");
478  int i, start_index, start_number;
479  double prog_date_time = 0;
480 
481  get_start_index_number(os, c, &start_index, &start_number);
482 
483  if (!c->hls_playlist || start_index >= os->nb_segments ||
485  return;
486 
487  get_hls_playlist_name(filename_hls, sizeof(filename_hls),
488  c->dirname, representation_id);
489 
490  snprintf(temp_filename_hls, sizeof(temp_filename_hls), use_rename ? "%s.tmp" : "%s", filename_hls);
491 
492  set_http_options(&http_opts, c);
493  ret = dashenc_io_open(s, &c->m3u8_out, temp_filename_hls, &http_opts);
494  av_dict_free(&http_opts);
495  if (ret < 0) {
496  handle_io_open_error(s, ret, temp_filename_hls);
497  return;
498  }
499  for (i = start_index; i < os->nb_segments; i++) {
500  Segment *seg = os->segments[i];
501  double duration = (double) seg->duration / timescale;
502  if (target_duration <= duration)
503  target_duration = lrint(duration);
504  }
505 
506  ff_hls_write_playlist_header(c->m3u8_out, 6, -1, target_duration,
507  start_number, PLAYLIST_TYPE_NONE, 0);
508 
509  ff_hls_write_init_file(c->m3u8_out, os->initfile, c->single_file,
511 
512  for (i = start_index; i < os->nb_segments; i++) {
513  Segment *seg = os->segments[i];
514 
515  if (prog_date_time == 0) {
516  if (os->nb_segments == 1)
517  prog_date_time = c->start_time_s;
518  else
519  prog_date_time = seg->prog_date_time;
520  }
521  seg->prog_date_time = prog_date_time;
522 
523  ret = ff_hls_write_file_entry(c->m3u8_out, 0, c->single_file,
524  (double) seg->duration / timescale, 0,
525  seg->range_length, seg->start_pos, NULL,
526  c->single_file ? os->initfile : seg->file,
527  &prog_date_time, 0, 0, 0);
528  if (ret < 0) {
529  av_log(os->ctx, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n");
530  }
531  }
532 
533  if (prefetch_url)
534  avio_printf(c->m3u8_out, "#EXT-X-PREFETCH:%s\n", prefetch_url);
535 
536  if (final)
537  ff_hls_write_end_list(c->m3u8_out);
538 
539  dashenc_io_close(s, &c->m3u8_out, temp_filename_hls);
540 
541  if (use_rename)
542  if (avpriv_io_move(temp_filename_hls, filename_hls) < 0) {
543  av_log(os->ctx, AV_LOG_WARNING, "renaming file %s to %s failed\n\n", temp_filename_hls, filename_hls);
544  }
545 }
546 
548 {
549  DASHContext *c = s->priv_data;
550  int ret, range_length;
551 
552  ret = flush_dynbuf(c, os, &range_length);
553  if (ret < 0)
554  return ret;
555 
556  os->pos = os->init_range_length = range_length;
557  if (!c->single_file) {
558  char filename[1024];
559  snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile);
560  dashenc_io_close(s, &os->out, filename);
561  }
562  return 0;
563 }
564 
566 {
567  DASHContext *c = s->priv_data;
568  int i, j;
569 
570  if (c->as) {
571  for (i = 0; i < c->nb_as; i++)
572  av_dict_free(&c->as[i].metadata);
573  av_freep(&c->as);
574  c->nb_as = 0;
575  }
576 
577  if (!c->streams)
578  return;
579  for (i = 0; i < s->nb_streams; i++) {
580  OutputStream *os = &c->streams[i];
581  if (os->ctx && os->ctx->pb) {
582  if (!c->single_file)
583  ffio_free_dyn_buf(&os->ctx->pb);
584  else
585  avio_close(os->ctx->pb);
586  }
587  ff_format_io_close(s, &os->out);
588  if (os->ctx)
590  for (j = 0; j < os->nb_segments; j++)
591  av_free(os->segments[j]);
592  av_free(os->segments);
594  av_freep(&os->init_seg_name);
595  av_freep(&os->media_seg_name);
596  }
597  av_freep(&c->streams);
598 
599  ff_format_io_close(s, &c->mpd_out);
600  ff_format_io_close(s, &c->m3u8_out);
601 }
602 
604  int representation_id, int final)
605 {
606  DASHContext *c = s->priv_data;
607  int i, start_index, start_number;
608  get_start_index_number(os, c, &start_index, &start_number);
609 
610  if (c->use_template) {
611  int timescale = c->use_timeline ? os->ctx->streams[0]->time_base.den : AV_TIME_BASE;
612  avio_printf(out, "\t\t\t\t<SegmentTemplate timescale=\"%d\" ", timescale);
613  if (!c->use_timeline) {
614  avio_printf(out, "duration=\"%"PRId64"\" ", c->seg_duration);
615  if (c->streaming && os->availability_time_offset)
616  avio_printf(out, "availabilityTimeOffset=\"%.3f\" ",
618  }
619  avio_printf(out, "initialization=\"%s\" media=\"%s\" startNumber=\"%d\">\n", os->init_seg_name, os->media_seg_name, c->use_timeline ? start_number : 1);
620  if (c->use_timeline) {
621  int64_t cur_time = 0;
622  avio_printf(out, "\t\t\t\t\t<SegmentTimeline>\n");
623  for (i = start_index; i < os->nb_segments; ) {
624  Segment *seg = os->segments[i];
625  int repeat = 0;
626  avio_printf(out, "\t\t\t\t\t\t<S ");
627  if (i == start_index || seg->time != cur_time) {
628  cur_time = seg->time;
629  avio_printf(out, "t=\"%"PRId64"\" ", seg->time);
630  }
631  avio_printf(out, "d=\"%"PRId64"\" ", seg->duration);
632  while (i + repeat + 1 < os->nb_segments &&
633  os->segments[i + repeat + 1]->duration == seg->duration &&
634  os->segments[i + repeat + 1]->time == os->segments[i + repeat]->time + os->segments[i + repeat]->duration)
635  repeat++;
636  if (repeat > 0)
637  avio_printf(out, "r=\"%d\" ", repeat);
638  avio_printf(out, "/>\n");
639  i += 1 + repeat;
640  cur_time += (1 + repeat) * seg->duration;
641  }
642  avio_printf(out, "\t\t\t\t\t</SegmentTimeline>\n");
643  }
644  avio_printf(out, "\t\t\t\t</SegmentTemplate>\n");
645  } else if (c->single_file) {
646  avio_printf(out, "\t\t\t\t<BaseURL>%s</BaseURL>\n", os->initfile);
647  avio_printf(out, "\t\t\t\t<SegmentList timescale=\"%d\" duration=\"%"PRId64"\" startNumber=\"%d\">\n", AV_TIME_BASE, c->last_duration, start_number);
648  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);
649  for (i = start_index; i < os->nb_segments; i++) {
650  Segment *seg = os->segments[i];
651  avio_printf(out, "\t\t\t\t\t<SegmentURL mediaRange=\"%"PRId64"-%"PRId64"\" ", seg->start_pos, seg->start_pos + seg->range_length - 1);
652  if (seg->index_length)
653  avio_printf(out, "indexRange=\"%"PRId64"-%"PRId64"\" ", seg->start_pos, seg->start_pos + seg->index_length - 1);
654  avio_printf(out, "/>\n");
655  }
656  avio_printf(out, "\t\t\t\t</SegmentList>\n");
657  } else {
658  avio_printf(out, "\t\t\t\t<SegmentList timescale=\"%d\" duration=\"%"PRId64"\" startNumber=\"%d\">\n", AV_TIME_BASE, c->last_duration, start_number);
659  avio_printf(out, "\t\t\t\t\t<Initialization sourceURL=\"%s\" />\n", os->initfile);
660  for (i = start_index; i < os->nb_segments; i++) {
661  Segment *seg = os->segments[i];
662  avio_printf(out, "\t\t\t\t\t<SegmentURL media=\"%s\" />\n", seg->file);
663  }
664  avio_printf(out, "\t\t\t\t</SegmentList>\n");
665  }
666  if (!c->lhls || final) {
667  write_hls_media_playlist(os, s, representation_id, final, NULL);
668  }
669 
670 }
671 
672 static char *xmlescape(const char *str) {
673  int outlen = strlen(str)*3/2 + 6;
674  char *out = av_realloc(NULL, outlen + 1);
675  int pos = 0;
676  if (!out)
677  return NULL;
678  for (; *str; str++) {
679  if (pos + 6 > outlen) {
680  char *tmp;
681  outlen = 2 * outlen + 6;
682  tmp = av_realloc(out, outlen + 1);
683  if (!tmp) {
684  av_free(out);
685  return NULL;
686  }
687  out = tmp;
688  }
689  if (*str == '&') {
690  memcpy(&out[pos], "&amp;", 5);
691  pos += 5;
692  } else if (*str == '<') {
693  memcpy(&out[pos], "&lt;", 4);
694  pos += 4;
695  } else if (*str == '>') {
696  memcpy(&out[pos], "&gt;", 4);
697  pos += 4;
698  } else if (*str == '\'') {
699  memcpy(&out[pos], "&apos;", 6);
700  pos += 6;
701  } else if (*str == '\"') {
702  memcpy(&out[pos], "&quot;", 6);
703  pos += 6;
704  } else {
705  out[pos++] = *str;
706  }
707  }
708  out[pos] = '\0';
709  return out;
710 }
711 
712 static void write_time(AVIOContext *out, int64_t time)
713 {
714  int seconds = time / AV_TIME_BASE;
715  int fractions = time % AV_TIME_BASE;
716  int minutes = seconds / 60;
717  int hours = minutes / 60;
718  seconds %= 60;
719  minutes %= 60;
720  avio_printf(out, "PT");
721  if (hours)
722  avio_printf(out, "%dH", hours);
723  if (hours || minutes)
724  avio_printf(out, "%dM", minutes);
725  avio_printf(out, "%d.%dS", seconds, fractions / (AV_TIME_BASE / 10));
726 }
727 
728 static void format_date_now(char *buf, int size)
729 {
730  struct tm *ptm, tmbuf;
731  int64_t time_us = av_gettime();
732  int64_t time_ms = time_us / 1000;
733  const time_t time_s = time_ms / 1000;
734  int millisec = time_ms - (time_s * 1000);
735  ptm = gmtime_r(&time_s, &tmbuf);
736  if (ptm) {
737  int len;
738  if (!strftime(buf, size, "%Y-%m-%dT%H:%M:%S", ptm)) {
739  buf[0] = '\0';
740  return;
741  }
742  len = strlen(buf);
743  snprintf(buf + len, size - len, ".%03dZ", millisec);
744  }
745 }
746 
748  int final)
749 {
750  DASHContext *c = s->priv_data;
751  AdaptationSet *as = &c->as[as_index];
752  AVDictionaryEntry *lang, *role;
753  int i;
754 
755  avio_printf(out, "\t\t<AdaptationSet id=\"%s\" contentType=\"%s\" segmentAlignment=\"true\" bitstreamSwitching=\"true\"",
756  as->id, as->media_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio");
758  avio_printf(out, " maxFrameRate=\"%d/%d\"", as->max_frame_rate.num, as->max_frame_rate.den);
759  lang = av_dict_get(as->metadata, "language", NULL, 0);
760  if (lang)
761  avio_printf(out, " lang=\"%s\"", lang->value);
762  avio_printf(out, ">\n");
763 
764  role = av_dict_get(as->metadata, "role", NULL, 0);
765  if (role)
766  avio_printf(out, "\t\t\t<Role schemeIdUri=\"urn:mpeg:dash:role:2011\" value=\"%s\"/>\n", role->value);
767 
768  for (i = 0; i < s->nb_streams; i++) {
769  OutputStream *os = &c->streams[i];
770  char bandwidth_str[64] = {'\0'};
771 
772  if (os->as_idx - 1 != as_index)
773  continue;
774 
775  if (os->bit_rate > 0)
776  snprintf(bandwidth_str, sizeof(bandwidth_str), " bandwidth=\"%d\"",
777  os->bit_rate);
778 
779  if (as->media_type == AVMEDIA_TYPE_VIDEO) {
780  AVStream *st = s->streams[i];
781  avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"video/%s\" codecs=\"%s\"%s width=\"%d\" height=\"%d\"",
782  i, os->format_name, os->codec_str, bandwidth_str, s->streams[i]->codecpar->width, s->streams[i]->codecpar->height);
783  if (st->avg_frame_rate.num)
784  avio_printf(out, " frameRate=\"%d/%d\"", st->avg_frame_rate.num, st->avg_frame_rate.den);
785  avio_printf(out, ">\n");
786  } else {
787  avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"audio/%s\" codecs=\"%s\"%s audioSamplingRate=\"%d\">\n",
788  i, os->format_name, os->codec_str, bandwidth_str, s->streams[i]->codecpar->sample_rate);
789  avio_printf(out, "\t\t\t\t<AudioChannelConfiguration schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\" value=\"%d\" />\n",
790  s->streams[i]->codecpar->channels);
791  }
792  output_segment_list(os, out, s, i, final);
793  avio_printf(out, "\t\t\t</Representation>\n");
794  }
795  avio_printf(out, "\t\t</AdaptationSet>\n");
796 
797  return 0;
798 }
799 
801 {
802  DASHContext *c = s->priv_data;
803 
804  void *mem = av_realloc(c->as, sizeof(*c->as) * (c->nb_as + 1));
805  if (!mem)
806  return AVERROR(ENOMEM);
807  c->as = mem;
808  ++c->nb_as;
809 
810  *as = &c->as[c->nb_as - 1];
811  memset(*as, 0, sizeof(**as));
812  (*as)->media_type = type;
813 
814  return 0;
815 }
816 
817 static int adaptation_set_add_stream(AVFormatContext *s, int as_idx, int i)
818 {
819  DASHContext *c = s->priv_data;
820  AdaptationSet *as = &c->as[as_idx - 1];
821  OutputStream *os = &c->streams[i];
822 
823  if (as->media_type != s->streams[i]->codecpar->codec_type) {
824  av_log(s, AV_LOG_ERROR, "Codec type of stream %d doesn't match AdaptationSet's media type\n", i);
825  return AVERROR(EINVAL);
826  } else if (os->as_idx) {
827  av_log(s, AV_LOG_ERROR, "Stream %d is already assigned to an AdaptationSet\n", i);
828  return AVERROR(EINVAL);
829  }
830  os->as_idx = as_idx;
831 
832  return 0;
833 }
834 
836 {
837  DASHContext *c = s->priv_data;
838  const char *p = c->adaptation_sets;
839  enum { new_set, parse_id, parsing_streams } state;
840  AdaptationSet *as;
841  int i, n, ret;
842 
843  // default: one AdaptationSet for each stream
844  if (!p) {
845  for (i = 0; i < s->nb_streams; i++) {
846  if ((ret = add_adaptation_set(s, &as, s->streams[i]->codecpar->codec_type)) < 0)
847  return ret;
848  snprintf(as->id, sizeof(as->id), "%d", i);
849 
850  c->streams[i].as_idx = c->nb_as;
851  }
852  goto end;
853  }
854 
855  // syntax id=0,streams=0,1,2 id=1,streams=3,4 and so on
856  state = new_set;
857  while (*p) {
858  if (*p == ' ') {
859  p++;
860  continue;
861  } else if (state == new_set && av_strstart(p, "id=", &p)) {
862 
863  if ((ret = add_adaptation_set(s, &as, AVMEDIA_TYPE_UNKNOWN)) < 0)
864  return ret;
865 
866  n = strcspn(p, ",");
867  snprintf(as->id, sizeof(as->id), "%.*s", n, p);
868 
869  p += n;
870  if (*p)
871  p++;
872  state = parse_id;
873  } else if (state == parse_id && av_strstart(p, "streams=", &p)) {
874  state = parsing_streams;
875  } else if (state == parsing_streams) {
876  AdaptationSet *as = &c->as[c->nb_as - 1];
877  char idx_str[8], *end_str;
878 
879  n = strcspn(p, " ,");
880  snprintf(idx_str, sizeof(idx_str), "%.*s", n, p);
881  p += n;
882 
883  // if value is "a" or "v", map all streams of that type
884  if (as->media_type == AVMEDIA_TYPE_UNKNOWN && (idx_str[0] == 'v' || idx_str[0] == 'a')) {
885  enum AVMediaType type = (idx_str[0] == 'v') ? AVMEDIA_TYPE_VIDEO : AVMEDIA_TYPE_AUDIO;
886  av_log(s, AV_LOG_DEBUG, "Map all streams of type %s\n", idx_str);
887 
888  for (i = 0; i < s->nb_streams; i++) {
889  if (s->streams[i]->codecpar->codec_type != type)
890  continue;
891 
892  as->media_type = s->streams[i]->codecpar->codec_type;
893 
894  if ((ret = adaptation_set_add_stream(s, c->nb_as, i)) < 0)
895  return ret;
896  }
897  } else { // select single stream
898  i = strtol(idx_str, &end_str, 10);
899  if (idx_str == end_str || i < 0 || i >= s->nb_streams) {
900  av_log(s, AV_LOG_ERROR, "Selected stream \"%s\" not found!\n", idx_str);
901  return AVERROR(EINVAL);
902  }
903  av_log(s, AV_LOG_DEBUG, "Map stream %d\n", i);
904 
905  if (as->media_type == AVMEDIA_TYPE_UNKNOWN) {
906  as->media_type = s->streams[i]->codecpar->codec_type;
907  }
908 
909  if ((ret = adaptation_set_add_stream(s, c->nb_as, i)) < 0)
910  return ret;
911  }
912 
913  if (*p == ' ')
914  state = new_set;
915  if (*p)
916  p++;
917  } else {
918  return AVERROR(EINVAL);
919  }
920  }
921 
922 end:
923  // check for unassigned streams
924  for (i = 0; i < s->nb_streams; i++) {
925  OutputStream *os = &c->streams[i];
926  if (!os->as_idx) {
927  av_log(s, AV_LOG_ERROR, "Stream %d is not mapped to an AdaptationSet\n", i);
928  return AVERROR(EINVAL);
929  }
930  }
931  return 0;
932 }
933 
934 static int write_manifest(AVFormatContext *s, int final)
935 {
936  DASHContext *c = s->priv_data;
937  AVIOContext *out;
938  char temp_filename[1024];
939  int ret, i;
940  const char *proto = avio_find_protocol_name(s->url);
941  int use_rename = proto && !strcmp(proto, "file");
942  static unsigned int warned_non_file = 0;
943  AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
945 
946  if (!use_rename && !warned_non_file++)
947  av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this may lead to races and temporary partial files\n");
948 
949  snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", s->url);
951  ret = dashenc_io_open(s, &c->mpd_out, temp_filename, &opts);
952  av_dict_free(&opts);
953  if (ret < 0) {
954  return handle_io_open_error(s, ret, temp_filename);
955  }
956  out = c->mpd_out;
957  avio_printf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
958  avio_printf(out, "<MPD xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
959  "\txmlns=\"urn:mpeg:dash:schema:mpd:2011\"\n"
960  "\txmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
961  "\txsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd\"\n"
962  "\tprofiles=\"urn:mpeg:dash:profile:isoff-live:2011\"\n"
963  "\ttype=\"%s\"\n", final ? "static" : "dynamic");
964  if (final) {
965  avio_printf(out, "\tmediaPresentationDuration=\"");
966  write_time(out, c->total_duration);
967  avio_printf(out, "\"\n");
968  } else {
969  int64_t update_period = c->last_duration / AV_TIME_BASE;
970  char now_str[100];
971  if (c->use_template && !c->use_timeline)
972  update_period = 500;
973  avio_printf(out, "\tminimumUpdatePeriod=\"PT%"PRId64"S\"\n", update_period);
974  avio_printf(out, "\tsuggestedPresentationDelay=\"PT%"PRId64"S\"\n", c->last_duration / AV_TIME_BASE);
975  if (c->availability_start_time[0])
976  avio_printf(out, "\tavailabilityStartTime=\"%s\"\n", c->availability_start_time);
977  format_date_now(now_str, sizeof(now_str));
978  if (now_str[0])
979  avio_printf(out, "\tpublishTime=\"%s\"\n", now_str);
980  if (c->window_size && c->use_template) {
981  avio_printf(out, "\ttimeShiftBufferDepth=\"");
982  write_time(out, c->last_duration * c->window_size);
983  avio_printf(out, "\"\n");
984  }
985  }
986  avio_printf(out, "\tminBufferTime=\"");
987  write_time(out, c->last_duration * 2);
988  avio_printf(out, "\">\n");
989  avio_printf(out, "\t<ProgramInformation>\n");
990  if (title) {
991  char *escaped = xmlescape(title->value);
992  avio_printf(out, "\t\t<Title>%s</Title>\n", escaped);
993  av_free(escaped);
994  }
995  avio_printf(out, "\t</ProgramInformation>\n");
996 
997  if (c->window_size && s->nb_streams > 0 && c->streams[0].nb_segments > 0 && !c->use_template) {
998  OutputStream *os = &c->streams[0];
999  int start_index = FFMAX(os->nb_segments - c->window_size, 0);
1000  int64_t start_time = av_rescale_q(os->segments[start_index]->time, s->streams[0]->time_base, AV_TIME_BASE_Q);
1001  avio_printf(out, "\t<Period id=\"0\" start=\"");
1003  avio_printf(out, "\">\n");
1004  } else {
1005  avio_printf(out, "\t<Period id=\"0\" start=\"PT0.0S\">\n");
1006  }
1007 
1008  for (i = 0; i < c->nb_as; i++) {
1009  if ((ret = write_adaptation_set(s, out, i, final)) < 0)
1010  return ret;
1011  }
1012  avio_printf(out, "\t</Period>\n");
1013 
1014  if (c->utc_timing_url)
1015  avio_printf(out, "\t<UTCTiming schemeIdUri=\"urn:mpeg:dash:utc:http-xsdate:2014\" value=\"%s\"/>\n", c->utc_timing_url);
1016 
1017  avio_printf(out, "</MPD>\n");
1018  avio_flush(out);
1019  dashenc_io_close(s, &c->mpd_out, temp_filename);
1020 
1021  if (use_rename) {
1022  if ((ret = avpriv_io_move(temp_filename, s->url)) < 0)
1023  return ret;
1024  }
1025 
1026  if (c->hls_playlist) {
1027  char filename_hls[1024];
1028  const char *audio_group = "A1";
1029  char audio_codec_str[128] = "\0";
1030  int is_default = 1;
1031  int max_audio_bitrate = 0;
1032 
1033  // Publish master playlist only the configured rate
1034  if (c->master_playlist_created && (!c->master_publish_rate ||
1035  c->streams[0].segment_index % c->master_publish_rate))
1036  return 0;
1037 
1038  if (*c->dirname)
1039  snprintf(filename_hls, sizeof(filename_hls), "%smaster.m3u8", c->dirname);
1040  else
1041  snprintf(filename_hls, sizeof(filename_hls), "master.m3u8");
1042 
1043  snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", filename_hls);
1044 
1045  set_http_options(&opts, c);
1046  ret = dashenc_io_open(s, &c->m3u8_out, temp_filename, &opts);
1047  av_dict_free(&opts);
1048  if (ret < 0) {
1049  return handle_io_open_error(s, ret, temp_filename);
1050  }
1051 
1052  ff_hls_write_playlist_version(c->m3u8_out, 7);
1053 
1054  for (i = 0; i < s->nb_streams; i++) {
1055  char playlist_file[64];
1056  AVStream *st = s->streams[i];
1057  OutputStream *os = &c->streams[i];
1059  continue;
1060  if (os->segment_type != SEGMENT_TYPE_MP4)
1061  continue;
1062  get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, i);
1063  ff_hls_write_audio_rendition(c->m3u8_out, (char *)audio_group,
1064  playlist_file, NULL, i, is_default);
1065  max_audio_bitrate = FFMAX(st->codecpar->bit_rate +
1066  os->muxer_overhead, max_audio_bitrate);
1067  if (!av_strnstr(audio_codec_str, os->codec_str, sizeof(audio_codec_str))) {
1068  if (strlen(audio_codec_str))
1069  av_strlcat(audio_codec_str, ",", sizeof(audio_codec_str));
1070  av_strlcat(audio_codec_str, os->codec_str, sizeof(audio_codec_str));
1071  }
1072  is_default = 0;
1073  }
1074 
1075  for (i = 0; i < s->nb_streams; i++) {
1076  char playlist_file[64];
1077  char codec_str[128];
1078  AVStream *st = s->streams[i];
1079  OutputStream *os = &c->streams[i];
1080  char *agroup = NULL;
1081  char *codec_str_ptr = NULL;
1082  int stream_bitrate = st->codecpar->bit_rate + os->muxer_overhead;
1084  continue;
1085  if (os->segment_type != SEGMENT_TYPE_MP4)
1086  continue;
1087  av_strlcpy(codec_str, os->codec_str, sizeof(codec_str));
1088  if (max_audio_bitrate) {
1089  agroup = (char *)audio_group;
1090  stream_bitrate += max_audio_bitrate;
1091  av_strlcat(codec_str, ",", sizeof(codec_str));
1092  av_strlcat(codec_str, audio_codec_str, sizeof(codec_str));
1093  }
1094  if (st->codecpar->codec_id != AV_CODEC_ID_HEVC) {
1095  codec_str_ptr = codec_str;
1096  }
1097  get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, i);
1098  ff_hls_write_stream_info(st, c->m3u8_out, stream_bitrate,
1099  playlist_file, agroup,
1100  codec_str_ptr, NULL);
1101  }
1102  dashenc_io_close(s, &c->m3u8_out, temp_filename);
1103  if (use_rename)
1104  if ((ret = avpriv_io_move(temp_filename, filename_hls)) < 0)
1105  return ret;
1106  c->master_playlist_created = 1;
1107  }
1108 
1109  return 0;
1110 }
1111 
1112 static int dict_copy_entry(AVDictionary **dst, const AVDictionary *src, const char *key)
1113 {
1114  AVDictionaryEntry *entry = av_dict_get(src, key, NULL, 0);
1115  if (entry)
1117  return 0;
1118 }
1119 
1121 {
1122  DASHContext *c = s->priv_data;
1123  int ret = 0, i;
1124  char *ptr;
1125  char basename[1024];
1126 
1127  c->nr_of_streams_to_flush = 0;
1128  if (c->single_file_name)
1129  c->single_file = 1;
1130  if (c->single_file)
1131  c->use_template = 0;
1132 
1133 #if FF_API_DASH_MIN_SEG_DURATION
1134  if (c->min_seg_duration != 5000000) {
1135  av_log(s, AV_LOG_WARNING, "The min_seg_duration option is deprecated and will be removed. Please use the -seg_duration\n");
1136  c->seg_duration = c->min_seg_duration;
1137  }
1138 #endif
1139  if (c->lhls && s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
1141  "LHLS is experimental, Please set -strict experimental in order to enable it.\n");
1142  return AVERROR_EXPERIMENTAL;
1143  }
1144 
1145  if (c->lhls && !c->streaming) {
1146  av_log(s, AV_LOG_WARNING, "LHLS option will be ignored as streaming is not enabled\n");
1147  c->lhls = 0;
1148  }
1149 
1150  if (c->lhls && !c->hls_playlist) {
1151  av_log(s, AV_LOG_WARNING, "LHLS option will be ignored as hls_playlist is not enabled\n");
1152  c->lhls = 0;
1153  }
1154 
1155  if (c->global_sidx && !c->single_file) {
1156  av_log(s, AV_LOG_WARNING, "Global SIDX option will be ignored as single_file is not enabled\n");
1157  c->global_sidx = 0;
1158  }
1159 
1160  if (c->global_sidx && c->streaming) {
1161  av_log(s, AV_LOG_WARNING, "Global SIDX option will be ignored as streaming is enabled\n");
1162  c->global_sidx = 0;
1163  }
1164 
1165  av_strlcpy(c->dirname, s->url, sizeof(c->dirname));
1166  ptr = strrchr(c->dirname, '/');
1167  if (ptr) {
1168  av_strlcpy(basename, &ptr[1], sizeof(basename));
1169  ptr[1] = '\0';
1170  } else {
1171  c->dirname[0] = '\0';
1172  av_strlcpy(basename, s->url, sizeof(basename));
1173  }
1174 
1175  ptr = strrchr(basename, '.');
1176  if (ptr)
1177  *ptr = '\0';
1178 
1179  c->streams = av_mallocz(sizeof(*c->streams) * s->nb_streams);
1180  if (!c->streams)
1181  return AVERROR(ENOMEM);
1182 
1183  if ((ret = parse_adaptation_sets(s)) < 0)
1184  return ret;
1185 
1186  if ((ret = init_segment_types(s)) < 0)
1187  return ret;
1188 
1189  for (i = 0; i < s->nb_streams; i++) {
1190  OutputStream *os = &c->streams[i];
1191  AdaptationSet *as = &c->as[os->as_idx - 1];
1193  AVStream *st;
1194  AVDictionary *opts = NULL;
1195  char filename[1024];
1196 
1197  os->bit_rate = s->streams[i]->codecpar->bit_rate;
1198  if (!os->bit_rate) {
1199  int level = s->strict_std_compliance >= FF_COMPLIANCE_STRICT ?
1201  av_log(s, level, "No bit rate set for stream %d\n", i);
1202  if (s->strict_std_compliance >= FF_COMPLIANCE_STRICT)
1203  return AVERROR(EINVAL);
1204  }
1205 
1206  // copy AdaptationSet language and role from stream metadata
1207  dict_copy_entry(&as->metadata, s->streams[i]->metadata, "language");
1208  dict_copy_entry(&as->metadata, s->streams[i]->metadata, "role");
1209 
1210  if (c->init_seg_name) {
1211  os->init_seg_name = av_strireplace(c->init_seg_name, "$ext$", os->extension_name);
1212  if (!os->init_seg_name)
1213  return AVERROR(ENOMEM);
1214  }
1215  if (c->media_seg_name) {
1216  os->media_seg_name = av_strireplace(c->media_seg_name, "$ext$", os->extension_name);
1217  if (!os->media_seg_name)
1218  return AVERROR(ENOMEM);
1219  }
1220  if (c->single_file_name) {
1221  os->single_file_name = av_strireplace(c->single_file_name, "$ext$", os->extension_name);
1222  if (!os->single_file_name)
1223  return AVERROR(ENOMEM);
1224  }
1225 
1226  if (os->segment_type == SEGMENT_TYPE_WEBM) {
1227  if ((!c->single_file && check_file_extension(os->init_seg_name, os->format_name) != 0) ||
1228  (!c->single_file && check_file_extension(os->media_seg_name, os->format_name) != 0) ||
1229  (c->single_file && check_file_extension(os->single_file_name, os->format_name) != 0)) {
1231  "One or many segment file names doesn't end with .webm. "
1232  "Override -init_seg_name and/or -media_seg_name and/or "
1233  "-single_file_name to end with the extension .webm\n");
1234  }
1235  if (c->streaming) {
1236  // Streaming not supported as matroskaenc buffers internally before writing the output
1237  av_log(s, AV_LOG_WARNING, "One or more streams in WebM output format. Streaming option will be ignored\n");
1238  c->streaming = 0;
1239  }
1240  }
1241 
1242  os->ctx = ctx = avformat_alloc_context();
1243  if (!ctx)
1244  return AVERROR(ENOMEM);
1245 
1247  if (!ctx->oformat)
1248  return AVERROR_MUXER_NOT_FOUND;
1249  ctx->interrupt_callback = s->interrupt_callback;
1250  ctx->opaque = s->opaque;
1251  ctx->io_close = s->io_close;
1252  ctx->io_open = s->io_open;
1253  ctx->strict_std_compliance = s->strict_std_compliance;
1254 
1255  if (!(st = avformat_new_stream(ctx, NULL)))
1256  return AVERROR(ENOMEM);
1257  avcodec_parameters_copy(st->codecpar, s->streams[i]->codecpar);
1258  st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio;
1259  st->time_base = s->streams[i]->time_base;
1260  st->avg_frame_rate = s->streams[i]->avg_frame_rate;
1261  ctx->avoid_negative_ts = s->avoid_negative_ts;
1262  ctx->flags = s->flags;
1263 
1264  if (c->single_file) {
1265  if (os->single_file_name)
1266  ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), os->single_file_name, i, 0, os->bit_rate, 0);
1267  else
1268  snprintf(os->initfile, sizeof(os->initfile), "%s-stream%d.%s", basename, i, os->format_name);
1269  } else {
1270  ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), os->init_seg_name, i, 0, os->bit_rate, 0);
1271  }
1272  snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile);
1273  set_http_options(&opts, c);
1274  if (!c->single_file) {
1275  if ((ret = avio_open_dyn_buf(&ctx->pb)) < 0)
1276  return ret;
1277  ret = s->io_open(s, &os->out, filename, AVIO_FLAG_WRITE, &opts);
1278  } else {
1279  ctx->url = av_strdup(filename);
1280  ret = avio_open2(&ctx->pb, filename, AVIO_FLAG_WRITE, NULL, &opts);
1281  }
1282  av_dict_free(&opts);
1283  if (ret < 0)
1284  return ret;
1285  os->init_start_pos = 0;
1286 
1287  if (c->format_options_str) {
1288  ret = av_dict_parse_string(&opts, c->format_options_str, "=", ":", 0);
1289  if (ret < 0)
1290  return ret;
1291  }
1292 
1293  if (os->segment_type == SEGMENT_TYPE_MP4) {
1294  if (c->streaming)
1295  // frag_every_frame : Allows lower latency streaming
1296  // skip_sidx : Reduce bitrate overhead
1297  // skip_trailer : Avoids growing memory usage with time
1298  av_dict_set(&opts, "movflags", "frag_every_frame+dash+delay_moov+skip_sidx+skip_trailer", 0);
1299  else {
1300  if (c->global_sidx)
1301  av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov+global_sidx+skip_trailer", 0);
1302  else
1303  av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov+skip_trailer", 0);
1304  }
1305  } else {
1306  av_dict_set_int(&opts, "cluster_time_limit", c->seg_duration / 1000, 0);
1307  av_dict_set_int(&opts, "cluster_size_limit", 5 * 1024 * 1024, 0); // set a large cluster size limit
1308  av_dict_set_int(&opts, "dash", 1, 0);
1309  av_dict_set_int(&opts, "dash_track_number", i + 1, 0);
1310  av_dict_set_int(&opts, "live", 1, 0);
1311  }
1313  av_dict_free(&opts);
1314  if (ret < 0)
1315  return ret;
1316  os->ctx_inited = 1;
1317  avio_flush(ctx->pb);
1318 
1319  av_log(s, AV_LOG_VERBOSE, "Representation %d init segment will be written to: %s\n", i, filename);
1320 
1321  s->streams[i]->time_base = st->time_base;
1322  // If the muxer wants to shift timestamps, request to have them shifted
1323  // already before being handed to this muxer, so we don't have mismatches
1324  // between the MPD and the actual segments.
1325  s->avoid_negative_ts = ctx->avoid_negative_ts;
1326  if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
1327  AVRational avg_frame_rate = s->streams[i]->avg_frame_rate;
1328  if (avg_frame_rate.num > 0) {
1329  if (av_cmp_q(avg_frame_rate, as->min_frame_rate) < 0)
1330  as->min_frame_rate = avg_frame_rate;
1331  if (av_cmp_q(as->max_frame_rate, avg_frame_rate) < 0)
1332  as->max_frame_rate = avg_frame_rate;
1333  } else {
1334  as->ambiguous_frame_rate = 1;
1335  }
1336  c->has_video = 1;
1337  }
1338 
1340  sizeof(os->codec_str));
1341  os->first_pts = AV_NOPTS_VALUE;
1342  os->max_pts = AV_NOPTS_VALUE;
1343  os->last_dts = AV_NOPTS_VALUE;
1344  os->segment_index = 1;
1345 
1346  if (s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
1347  c->nr_of_streams_to_flush++;
1348  }
1349 
1350  if (!c->has_video && c->seg_duration <= 0) {
1351  av_log(s, AV_LOG_WARNING, "no video stream and no seg duration set\n");
1352  return AVERROR(EINVAL);
1353  }
1354 
1355  c->nr_of_streams_flushed = 0;
1356 
1357  return 0;
1358 }
1359 
1361 {
1362  DASHContext *c = s->priv_data;
1363  int i, ret;
1364  for (i = 0; i < s->nb_streams; i++) {
1365  OutputStream *os = &c->streams[i];
1366  if ((ret = avformat_write_header(os->ctx, NULL)) < 0)
1367  return ret;
1368 
1369  // Flush init segment
1370  // Only for WebM segment, since for mp4 delay_moov is set and
1371  // the init segment is thus flushed after the first packets.
1372  if (os->segment_type == SEGMENT_TYPE_WEBM &&
1373  (ret = flush_init_segment(s, os)) < 0)
1374  return ret;
1375  }
1376  return ret;
1377 }
1378 
1379 static int add_segment(OutputStream *os, const char *file,
1380  int64_t time, int64_t duration,
1381  int64_t start_pos, int64_t range_length,
1382  int64_t index_length, int next_exp_index)
1383 {
1384  int err;
1385  Segment *seg;
1386  if (os->nb_segments >= os->segments_size) {
1387  os->segments_size = (os->segments_size + 1) * 2;
1388  if ((err = av_reallocp(&os->segments, sizeof(*os->segments) *
1389  os->segments_size)) < 0) {
1390  os->segments_size = 0;
1391  os->nb_segments = 0;
1392  return err;
1393  }
1394  }
1395  seg = av_mallocz(sizeof(*seg));
1396  if (!seg)
1397  return AVERROR(ENOMEM);
1398  av_strlcpy(seg->file, file, sizeof(seg->file));
1399  seg->time = time;
1400  seg->duration = duration;
1401  if (seg->time < 0) { // If pts<0, it is expected to be cut away with an edit list
1402  seg->duration += seg->time;
1403  seg->time = 0;
1404  }
1405  seg->start_pos = start_pos;
1406  seg->range_length = range_length;
1407  seg->index_length = index_length;
1408  os->segments[os->nb_segments++] = seg;
1409  os->segment_index++;
1410  //correcting the segment index if it has fallen behind the expected value
1411  if (os->segment_index < next_exp_index) {
1412  av_log(NULL, AV_LOG_WARNING, "Correcting the segment index after file %s: current=%d corrected=%d\n",
1413  file, os->segment_index, next_exp_index);
1414  os->segment_index = next_exp_index;
1415  }
1416  return 0;
1417 }
1418 
1419 static void write_styp(AVIOContext *pb)
1420 {
1421  avio_wb32(pb, 24);
1422  ffio_wfourcc(pb, "styp");
1423  ffio_wfourcc(pb, "msdh");
1424  avio_wb32(pb, 0); /* minor */
1425  ffio_wfourcc(pb, "msdh");
1426  ffio_wfourcc(pb, "msix");
1427 }
1428 
1429 static void find_index_range(AVFormatContext *s, const char *full_path,
1430  int64_t pos, int *index_length)
1431 {
1432  uint8_t buf[8];
1433  AVIOContext *pb;
1434  int ret;
1435 
1436  ret = s->io_open(s, &pb, full_path, AVIO_FLAG_READ, NULL);
1437  if (ret < 0)
1438  return;
1439  if (avio_seek(pb, pos, SEEK_SET) != pos) {
1440  ff_format_io_close(s, &pb);
1441  return;
1442  }
1443  ret = avio_read(pb, buf, 8);
1444  ff_format_io_close(s, &pb);
1445  if (ret < 8)
1446  return;
1447  if (AV_RL32(&buf[4]) != MKTAG('s', 'i', 'd', 'x'))
1448  return;
1449  *index_length = AV_RB32(&buf[0]);
1450 }
1451 
1453  AVPacket *pkt, AVRational *frame_rate)
1454 {
1455  AVCodecParameters *par = os->ctx->streams[0]->codecpar;
1456  uint8_t *extradata;
1457  int ret, extradata_size;
1458 
1459  if (par->extradata_size)
1460  return 0;
1461 
1462  extradata = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &extradata_size);
1463  if (!extradata_size)
1464  return 0;
1465 
1466  ret = ff_alloc_extradata(par, extradata_size);
1467  if (ret < 0)
1468  return ret;
1469 
1470  memcpy(par->extradata, extradata, extradata_size);
1471 
1472  set_codec_str(s, par, frame_rate, os->codec_str, sizeof(os->codec_str));
1473 
1474  return 0;
1475 }
1476 
1477 static void dashenc_delete_file(AVFormatContext *s, char *filename) {
1478  DASHContext *c = s->priv_data;
1479  int http_base_proto = ff_is_http_proto(filename);
1480 
1481  if (http_base_proto) {
1482  AVIOContext *out = NULL;
1483  AVDictionary *http_opts = NULL;
1484 
1485  set_http_options(&http_opts, c);
1486  av_dict_set(&http_opts, "method", "DELETE", 0);
1487 
1488  if (dashenc_io_open(s, &out, filename, &http_opts) < 0) {
1489  av_log(s, AV_LOG_ERROR, "failed to delete %s\n", filename);
1490  }
1491 
1492  av_dict_free(&http_opts);
1494  } else {
1495  int res = avpriv_io_delete(filename);
1496  if (res < 0) {
1497  char errbuf[AV_ERROR_MAX_STRING_SIZE];
1498  av_strerror(res, errbuf, sizeof(errbuf));
1499  av_log(s, (res == AVERROR(ENOENT) ? AV_LOG_WARNING : AV_LOG_ERROR), "failed to delete %s: %s\n", filename, errbuf);
1500  }
1501  }
1502 }
1503 
1504 static int dashenc_delete_segment_file(AVFormatContext *s, const char* file)
1505 {
1506  DASHContext *c = s->priv_data;
1507  size_t dirname_len, file_len;
1508  char filename[1024];
1509 
1510  dirname_len = strlen(c->dirname);
1511  if (dirname_len >= sizeof(filename)) {
1512  av_log(s, AV_LOG_WARNING, "Cannot delete segments as the directory path is too long: %"PRIu64" characters: %s\n",
1513  (uint64_t)dirname_len, c->dirname);
1514  return AVERROR(ENAMETOOLONG);
1515  }
1516 
1517  memcpy(filename, c->dirname, dirname_len);
1518 
1519  file_len = strlen(file);
1520  if ((dirname_len + file_len) >= sizeof(filename)) {
1521  av_log(s, AV_LOG_WARNING, "Cannot delete segments as the path is too long: %"PRIu64" characters: %s%s\n",
1522  (uint64_t)(dirname_len + file_len), c->dirname, file);
1523  return AVERROR(ENAMETOOLONG);
1524  }
1525 
1526  memcpy(filename + dirname_len, file, file_len + 1); // include the terminating zero
1527  dashenc_delete_file(s, filename);
1528 
1529  return 0;
1530 }
1531 
1532 static inline void dashenc_delete_media_segments(AVFormatContext *s, OutputStream *os, int remove_count)
1533 {
1534  for (int i = 0; i < remove_count; ++i) {
1536 
1537  // Delete the segment regardless of whether the file was successfully deleted
1538  av_free(os->segments[i]);
1539  }
1540 
1541  os->nb_segments -= remove_count;
1542  memmove(os->segments, os->segments + remove_count, os->nb_segments * sizeof(*os->segments));
1543 }
1544 
1545 static int dash_flush(AVFormatContext *s, int final, int stream)
1546 {
1547  DASHContext *c = s->priv_data;
1548  int i, ret = 0;
1549 
1550  const char *proto = avio_find_protocol_name(s->url);
1551  int use_rename = proto && !strcmp(proto, "file");
1552 
1553  int cur_flush_segment_index = 0, next_exp_index = -1;
1554  if (stream >= 0) {
1555  cur_flush_segment_index = c->streams[stream].segment_index;
1556 
1557  //finding the next segment's expected index, based on the current pts value
1558  if (c->use_template && !c->use_timeline && c->index_correction &&
1559  c->streams[stream].last_pts != AV_NOPTS_VALUE &&
1560  c->streams[stream].first_pts != AV_NOPTS_VALUE) {
1561  int64_t pts_diff = av_rescale_q(c->streams[stream].last_pts -
1562  c->streams[stream].first_pts,
1563  s->streams[stream]->time_base,
1564  AV_TIME_BASE_Q);
1565  next_exp_index = (pts_diff / c->seg_duration) + 1;
1566  }
1567  }
1568 
1569  for (i = 0; i < s->nb_streams; i++) {
1570  OutputStream *os = &c->streams[i];
1571  AVStream *st = s->streams[i];
1572  int range_length, index_length = 0;
1573 
1574  if (!os->packets_written)
1575  continue;
1576 
1577  // Flush the single stream that got a keyframe right now.
1578  // Flush all audio streams as well, in sync with video keyframes,
1579  // but not the other video streams.
1580  if (stream >= 0 && i != stream) {
1581  if (s->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
1582  continue;
1583  // Make sure we don't flush audio streams multiple times, when
1584  // all video streams are flushed one at a time.
1585  if (c->has_video && os->segment_index > cur_flush_segment_index)
1586  continue;
1587  }
1588 
1589  if (!c->single_file) {
1590  if (os->segment_type == SEGMENT_TYPE_MP4 && !os->written_len)
1591  write_styp(os->ctx->pb);
1592  } else {
1593  snprintf(os->full_path, sizeof(os->full_path), "%s%s", c->dirname, os->initfile);
1594  }
1595 
1596  ret = flush_dynbuf(c, os, &range_length);
1597  if (ret < 0)
1598  break;
1599  os->packets_written = 0;
1600 
1601  if (c->single_file) {
1602  find_index_range(s, os->full_path, os->pos, &index_length);
1603  } else {
1604  dashenc_io_close(s, &os->out, os->temp_path);
1605 
1606  if (use_rename) {
1607  ret = avpriv_io_move(os->temp_path, os->full_path);
1608  if (ret < 0)
1609  break;
1610  }
1611  }
1612 
1613  if (!os->muxer_overhead)
1614  os->muxer_overhead = ((int64_t) (range_length - os->total_pkt_size) *
1615  8 * AV_TIME_BASE) /
1616  av_rescale_q(os->max_pts - os->start_pts,
1617  st->time_base, AV_TIME_BASE_Q);
1618  os->total_pkt_size = 0;
1619 
1620  if (!os->bit_rate) {
1621  // calculate average bitrate of first segment
1622  int64_t bitrate = (int64_t) range_length * 8 * AV_TIME_BASE / av_rescale_q(os->max_pts - os->start_pts,
1623  st->time_base,
1624  AV_TIME_BASE_Q);
1625  if (bitrate >= 0)
1626  os->bit_rate = bitrate;
1627  }
1628  add_segment(os, os->filename, os->start_pts, os->max_pts - os->start_pts, os->pos, range_length, index_length, next_exp_index);
1629  av_log(s, AV_LOG_VERBOSE, "Representation %d media segment %d written to: %s\n", i, os->segment_index, os->full_path);
1630 
1631  os->pos += range_length;
1632  }
1633 
1634  if (c->window_size) {
1635  for (i = 0; i < s->nb_streams; i++) {
1636  OutputStream *os = &c->streams[i];
1637  int remove_count = os->nb_segments - c->window_size - c->extra_window_size;
1638  if (remove_count > 0)
1639  dashenc_delete_media_segments(s, os, remove_count);
1640  }
1641  }
1642 
1643  if (final) {
1644  for (i = 0; i < s->nb_streams; i++) {
1645  OutputStream *os = &c->streams[i];
1646  if (os->ctx && os->ctx_inited) {
1647  int64_t file_size = avio_tell(os->ctx->pb);
1648  av_write_trailer(os->ctx);
1649  if (c->global_sidx) {
1650  int j, start_index, start_number;
1651  int64_t sidx_size = avio_tell(os->ctx->pb) - file_size;
1652  get_start_index_number(os, c, &start_index, &start_number);
1653  if (start_index >= os->nb_segments ||
1655  continue;
1656  os->init_range_length += sidx_size;
1657  for (j = start_index; j < os->nb_segments; j++) {
1658  Segment *seg = os->segments[j];
1659  seg->start_pos += sidx_size;
1660  }
1661  }
1662 
1663  }
1664  }
1665  }
1666  if (ret >= 0) {
1667  if (c->has_video && !final) {
1668  c->nr_of_streams_flushed++;
1669  if (c->nr_of_streams_flushed != c->nr_of_streams_to_flush)
1670  return ret;
1671 
1672  c->nr_of_streams_flushed = 0;
1673  }
1674  ret = write_manifest(s, final);
1675  }
1676  return ret;
1677 }
1678 
1680 {
1681  DASHContext *c = s->priv_data;
1682  AVStream *st = s->streams[pkt->stream_index];
1683  OutputStream *os = &c->streams[pkt->stream_index];
1684  int64_t seg_end_duration, elapsed_duration;
1685  int ret;
1686 
1688  if (ret < 0)
1689  return ret;
1690 
1691  // Fill in a heuristic guess of the packet duration, if none is available.
1692  // The mp4 muxer will do something similar (for the last packet in a fragment)
1693  // if nothing is set (setting it for the other packets doesn't hurt).
1694  // By setting a nonzero duration here, we can be sure that the mp4 muxer won't
1695  // invoke its heuristic (this doesn't have to be identical to that algorithm),
1696  // so that we know the exact timestamps of fragments.
1697  if (!pkt->duration && os->last_dts != AV_NOPTS_VALUE)
1698  pkt->duration = pkt->dts - os->last_dts;
1699  os->last_dts = pkt->dts;
1700 
1701  // If forcing the stream to start at 0, the mp4 muxer will set the start
1702  // timestamps to 0. Do the same here, to avoid mismatches in duration/timestamps.
1703  if (os->first_pts == AV_NOPTS_VALUE &&
1704  s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO) {
1705  pkt->pts -= pkt->dts;
1706  pkt->dts = 0;
1707  }
1708 
1709  if (os->first_pts == AV_NOPTS_VALUE)
1710  os->first_pts = pkt->pts;
1711  os->last_pts = pkt->pts;
1712 
1713  if (!c->availability_start_time[0]) {
1714  int64_t start_time_us = av_gettime();
1715  c->start_time_s = start_time_us / 1000000;
1716  format_date_now(c->availability_start_time,
1717  sizeof(c->availability_start_time));
1718  }
1719 
1720  if (!os->availability_time_offset && pkt->duration) {
1721  int64_t frame_duration = av_rescale_q(pkt->duration, st->time_base,
1722  AV_TIME_BASE_Q);
1723  os->availability_time_offset = ((double) c->seg_duration -
1724  frame_duration) / AV_TIME_BASE;
1725  }
1726 
1727  if (c->use_template && !c->use_timeline) {
1728  elapsed_duration = pkt->pts - os->first_pts;
1729  seg_end_duration = (int64_t) os->segment_index * c->seg_duration;
1730  } else {
1731  elapsed_duration = pkt->pts - os->start_pts;
1732  seg_end_duration = c->seg_duration;
1733  }
1734 
1735  if ((!c->has_video || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) &&
1737  av_compare_ts(elapsed_duration, st->time_base,
1738  seg_end_duration, AV_TIME_BASE_Q) >= 0) {
1739  int64_t prev_duration = c->last_duration;
1740 
1741  c->last_duration = av_rescale_q(pkt->pts - os->start_pts,
1742  st->time_base,
1743  AV_TIME_BASE_Q);
1744  c->total_duration = av_rescale_q(pkt->pts - os->first_pts,
1745  st->time_base,
1746  AV_TIME_BASE_Q);
1747 
1748  if ((!c->use_timeline || !c->use_template) && prev_duration) {
1749  if (c->last_duration < prev_duration*9/10 ||
1750  c->last_duration > prev_duration*11/10) {
1752  "Segment durations differ too much, enable use_timeline "
1753  "and use_template, or keep a stricter keyframe interval\n");
1754  }
1755  }
1756 
1757  if ((ret = dash_flush(s, 0, pkt->stream_index)) < 0)
1758  return ret;
1759  }
1760 
1761  if (!os->packets_written) {
1762  // If we wrote a previous segment, adjust the start time of the segment
1763  // to the end of the previous one (which is the same as the mp4 muxer
1764  // does). This avoids gaps in the timeline.
1765  if (os->max_pts != AV_NOPTS_VALUE)
1766  os->start_pts = os->max_pts;
1767  else
1768  os->start_pts = pkt->pts;
1769  }
1770  if (os->max_pts == AV_NOPTS_VALUE)
1771  os->max_pts = pkt->pts + pkt->duration;
1772  else
1773  os->max_pts = FFMAX(os->max_pts, pkt->pts + pkt->duration);
1774  os->packets_written++;
1775  os->total_pkt_size += pkt->size;
1776  if ((ret = ff_write_chained(os->ctx, 0, pkt, s, 0)) < 0)
1777  return ret;
1778 
1779  if (!os->init_range_length)
1780  flush_init_segment(s, os);
1781 
1782  //open the output context when the first frame of a segment is ready
1783  if (!c->single_file && os->packets_written == 1) {
1784  AVDictionary *opts = NULL;
1785  const char *proto = avio_find_protocol_name(s->url);
1786  int use_rename = proto && !strcmp(proto, "file");
1787  os->filename[0] = os->full_path[0] = os->temp_path[0] = '\0';
1788  ff_dash_fill_tmpl_params(os->filename, sizeof(os->filename),
1790  os->segment_index, os->bit_rate, os->start_pts);
1791  snprintf(os->full_path, sizeof(os->full_path), "%s%s", c->dirname,
1792  os->filename);
1793  snprintf(os->temp_path, sizeof(os->temp_path),
1794  use_rename ? "%s.tmp" : "%s", os->full_path);
1795  set_http_options(&opts, c);
1796  ret = dashenc_io_open(s, &os->out, os->temp_path, &opts);
1797  av_dict_free(&opts);
1798  if (ret < 0) {
1799  return handle_io_open_error(s, ret, os->temp_path);
1800  }
1801  if (c->lhls) {
1802  char *prefetch_url = use_rename ? NULL : os->filename;
1803  write_hls_media_playlist(os, s, pkt->stream_index, 0, prefetch_url);
1804  }
1805  }
1806 
1807  //write out the data immediately in streaming mode
1808  if (c->streaming && os->segment_type == SEGMENT_TYPE_MP4) {
1809  int len = 0;
1810  uint8_t *buf = NULL;
1811  if (!os->written_len)
1812  write_styp(os->ctx->pb);
1813  avio_flush(os->ctx->pb);
1814  len = avio_get_dyn_buf (os->ctx->pb, &buf);
1815  if (os->out) {
1816  avio_write(os->out, buf + os->written_len, len - os->written_len);
1817  avio_flush(os->out);
1818  }
1819  os->written_len = len;
1820  }
1821 
1822  return ret;
1823 }
1824 
1826 {
1827  DASHContext *c = s->priv_data;
1828  int i;
1829 
1830  if (s->nb_streams > 0) {
1831  OutputStream *os = &c->streams[0];
1832  // If no segments have been written so far, try to do a crude
1833  // guess of the segment duration
1834  if (!c->last_duration)
1835  c->last_duration = av_rescale_q(os->max_pts - os->start_pts,
1836  s->streams[0]->time_base,
1837  AV_TIME_BASE_Q);
1838  c->total_duration = av_rescale_q(os->max_pts - os->first_pts,
1839  s->streams[0]->time_base,
1840  AV_TIME_BASE_Q);
1841  }
1842  dash_flush(s, 1, -1);
1843 
1844  if (c->remove_at_exit) {
1845  for (i = 0; i < s->nb_streams; ++i) {
1846  OutputStream *os = &c->streams[i];
1849  if (c->hls_playlist && os->segment_type == SEGMENT_TYPE_MP4) {
1850  char filename[1024];
1851  get_hls_playlist_name(filename, sizeof(filename), c->dirname, i);
1852  dashenc_delete_file(s, filename);
1853  }
1854  }
1855  dashenc_delete_file(s, s->url);
1856 
1857  if (c->hls_playlist && c->master_playlist_created) {
1858  char filename[1024];
1859  snprintf(filename, sizeof(filename), "%smaster.m3u8", c->dirname);
1860  dashenc_delete_file(s, filename);
1861  }
1862  }
1863 
1864  return 0;
1865 }
1866 
1867 static int dash_check_bitstream(struct AVFormatContext *s, const AVPacket *avpkt)
1868 {
1869  DASHContext *c = s->priv_data;
1870  OutputStream *os = &c->streams[avpkt->stream_index];
1871  AVFormatContext *oc = os->ctx;
1872  if (oc->oformat->check_bitstream) {
1873  int ret;
1874  AVPacket pkt = *avpkt;
1875  pkt.stream_index = 0;
1876  ret = oc->oformat->check_bitstream(oc, &pkt);
1877  if (ret == 1) {
1878  AVStream *st = s->streams[avpkt->stream_index];
1879  AVStream *ost = oc->streams[0];
1880  st->internal->bsfcs = ost->internal->bsfcs;
1882  ost->internal->bsfcs = NULL;
1883  ost->internal->nb_bsfcs = 0;
1884  }
1885  return ret;
1886  }
1887  return 1;
1888 }
1889 
1890 #define OFFSET(x) offsetof(DASHContext, x)
1891 #define E AV_OPT_FLAG_ENCODING_PARAM
1892 static const AVOption options[] = {
1893  { "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 },
1894  { "window_size", "number of segments kept in the manifest", OFFSET(window_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, E },
1895  { "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 },
1896 #if FF_API_DASH_MIN_SEG_DURATION
1897  { "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 },
1898 #endif
1899  { "seg_duration", "segment duration (in seconds, fractional value can be set)", OFFSET(seg_duration), AV_OPT_TYPE_DURATION, { .i64 = 5000000 }, 0, INT_MAX, E },
1900  { "remove_at_exit", "remove all segments when finished", OFFSET(remove_at_exit), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1901  { "use_template", "Use SegmentTemplate instead of SegmentList", OFFSET(use_template), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },
1902  { "use_timeline", "Use SegmentTimeline in SegmentTemplate", OFFSET(use_timeline), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },
1903  { "single_file", "Store all segments in one file, accessed using byte ranges", OFFSET(single_file), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1904  { "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 },
1905  { "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 },
1906  { "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 },
1907  { "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 },
1908  { "method", "set the HTTP method", OFFSET(method), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
1909  { "http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
1910  { "http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
1911  { "hls_playlist", "Generate HLS playlist files(master.m3u8, media_%d.m3u8)", OFFSET(hls_playlist), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1912  { "streaming", "Enable/Disable streaming mode of output. Each frame will be moof fragment", OFFSET(streaming), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1913  { "timeout", "set timeout for socket I/O operations", OFFSET(timeout), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT_MAX, .flags = E },
1914  { "index_correction", "Enable/Disable segment index correction logic", OFFSET(index_correction), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1915  { "format_options","set list of options for the container format (mp4/webm) used for dash", OFFSET(format_options_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
1916  { "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 },
1917  { "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"},
1918  { "auto", "select segment file format based on codec", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_AUTO }, 0, UINT_MAX, E, "segment_type"},
1919  { "mp4", "make segment file in ISOBMFF format", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_MP4 }, 0, UINT_MAX, E, "segment_type"},
1920  { "webm", "make segment file in WebM format", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_WEBM }, 0, UINT_MAX, E, "segment_type"},
1921  { "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 },
1922  { "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 },
1923  { "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},
1924  { NULL },
1925 };
1926 
1927 static const AVClass dash_class = {
1928  .class_name = "dash muxer",
1929  .item_name = av_default_item_name,
1930  .option = options,
1931  .version = LIBAVUTIL_VERSION_INT,
1932 };
1933 
1935  .name = "dash",
1936  .long_name = NULL_IF_CONFIG_SMALL("DASH Muxer"),
1937  .extensions = "mpd",
1938  .priv_data_size = sizeof(DASHContext),
1939  .audio_codec = AV_CODEC_ID_AAC,
1940  .video_codec = AV_CODEC_ID_H264,
1942  .init = dash_init,
1946  .deinit = dash_free,
1947  .check_bitstream = dash_check_bitstream,
1948  .priv_class = &dash_class,
1949 };
OutputStream::as_idx
int as_idx
Definition: dashenc.c:80
Segment::n
int n
Definition: dashenc.c:67
formats
formats
Definition: signature.h:48
options
static const AVOption options[]
Definition: dashenc.c:1892
DASHContext::remove_at_exit
int remove_at_exit
Definition: dashenc.c:119
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
DASHContext::master_playlist_created
int master_playlist_created
Definition: dashenc.c:138
AVCodecParameters::extradata
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: avcodec.h:3971
AdaptationSet::max_frame_rate
AVRational max_frame_rate
Definition: dashenc.c:74
AVERROR_EXPERIMENTAL
#define AVERROR_EXPERIMENTAL
Requested feature is flagged experimental. Set strict_std_compliance if you really want to use it.
Definition: error.h:72
DASHContext::as
AdaptationSet * as
Definition: dashenc.c:111
DASHContext::last_duration
int64_t last_duration
Definition: dashenc.c:125
level
uint8_t level
Definition: svq3.c:207
init
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
AVOutputFormat::name
const char * name
Definition: avformat.h:496
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
avformat_new_stream
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4480
AVCodecParameters::codec_type
enum AVMediaType codec_type
General type of the encoded data.
Definition: avcodec.h:3953
AV_WL32
#define AV_WL32(p, v)
Definition: intreadwrite.h:426
codec_id
enum AVCodecID codec_id
Definition: qsv.c:72
av_compare_ts
int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b)
Compare two timestamps each in its own time base.
Definition: mathematics.c:147
ffio_wfourcc
static av_always_inline void ffio_wfourcc(AVIOContext *pb, const uint8_t *s)
Definition: avio_internal.h:58
avio_close
int avio_close(AVIOContext *s)
Close the resource accessed by the AVIOContext s and free it.
Definition: aviobuf.c:1185
OutputStream::format_name
const char * format_name
Definition: dashenc.c:92
out
FILE * out
Definition: movenc.c:54
FF_COMPLIANCE_EXPERIMENTAL
#define FF_COMPLIANCE_EXPERIMENTAL
Allow nonstandardized experimental things.
Definition: avcodec.h:2633
ff_mp4_obj_type
const AVCodecTag ff_mp4_obj_type[]
Definition: isom.c:34
AVCodecParameters
This struct describes the properties of an encoded stream.
Definition: avcodec.h:3949
n
int n
Definition: avisynth_c.h:760
ff_isom_get_vpcc_features
int ff_isom_get_vpcc_features(AVFormatContext *s, AVCodecParameters *par, AVRational *frame_rate, VPCC *vpcc)
Definition: vpcc.c:116
ff_hls_write_end_list
void ff_hls_write_end_list(AVIOContext *out)
Definition: hlsplaylist.c:164
DASHContext::index_correction
int index_correction
Definition: dashenc.c:143
AdaptationSet::metadata
AVDictionary * metadata
Definition: dashenc.c:73
MKTAG
#define MKTAG(a, b, c, d)
Definition: common.h:366
dict_copy_entry
static int dict_copy_entry(AVDictionary **dst, const AVDictionary *src, const char *key)
Definition: dashenc.c:1112
rational.h
OutputStream::start_pts
int64_t start_pts
Definition: dashenc.c:88
AV_TIME_BASE_Q
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:260
codecs
static struct codec_string codecs[]
OutputStream::packets_written
int packets_written
Definition: dashenc.c:82
DASHContext::timeout
int64_t timeout
Definition: dashenc.c:142
DASHContext::http_persistent
int http_persistent
Definition: dashenc.c:137
DASHContext::format_options_str
char * format_options_str
Definition: dashenc.c:144
set_http_options
static void set_http_options(AVDictionary **options, DASHContext *c)
Definition: dashenc.c:436
parse_adaptation_sets
static int parse_adaptation_sets(AVFormatContext *s)
Definition: dashenc.c:835
update_stream_extradata
static int update_stream_extradata(AVFormatContext *s, OutputStream *os, AVPacket *pkt, AVRational *frame_rate)
Definition: dashenc.c:1452
end
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
tmp
static uint8_t tmp[11]
Definition: aes_ctr.c:26
AVFormatContext::streams
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1410
AVFormatContext::strict_std_compliance
int strict_std_compliance
Allow non-standard and experimental extension.
Definition: avformat.h:1650
set_codec_str
static void set_codec_str(AVFormatContext *s, AVCodecParameters *par, AVRational *frame_rate, char *str, int size)
Definition: dashenc.c:311
OutputStream::last_dts
int64_t last_dts
Definition: dashenc.c:89
dash_init
static int dash_init(AVFormatContext *s)
Definition: dashenc.c:1120
AVStream::internal
AVStreamInternal * internal
An opaque field for libavformat internal usage.
Definition: avformat.h:1227
AVOption
AVOption.
Definition: opt.h:246
AVStream::avg_frame_rate
AVRational avg_frame_rate
Average framerate.
Definition: avformat.h:943
AV_OPT_TYPE_DURATION
@ AV_OPT_TYPE_DURATION
Definition: opt.h:237
AVOutputFormat::check_bitstream
int(* check_bitstream)(struct AVFormatContext *, const AVPacket *pkt)
Set up any necessary bitstream filtering and extract any extra data needed for the global header.
Definition: avformat.h:630
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
AdaptationSet::id
char id[10]
Definition: dashenc.c:71
AVPacket::duration
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: avcodec.h:1495
AVCodecParameters::codec_tag
uint32_t codec_tag
Additional information about the codec (corresponds to the AVI FOURCC).
Definition: avcodec.h:3961
PLAYLIST_TYPE_NONE
@ PLAYLIST_TYPE_NONE
Definition: hlsplaylist.h:33
mathematics.h
dashenc_io_close
static void dashenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename)
Definition: dashenc.c:195
AVDictionary
Definition: dict.c:30
AV_CODEC_ID_FLAC
@ AV_CODEC_ID_FLAC
Definition: avcodec.h:576
AdaptationSet::min_frame_rate
AVRational min_frame_rate
Definition: dashenc.c:74
avformat_init_output
av_warn_unused_result int avformat_init_output(AVFormatContext *s, AVDictionary **options)
Allocate the stream private data and initialize the codec, but do not write the header.
Definition: mux.c:488
codec_string::str
const char * str
Definition: dashenc.c:156
DASHContext::global_sidx
int global_sidx
Definition: dashenc.c:145
SEGMENT_TYPE_MP4
@ SEGMENT_TYPE_MP4
Definition: dashenc.c:55
av_strlcatf
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition: avstring.c:101
ost
static AVStream * ost
Definition: vaapi_transcode.c:45
avio_get_dyn_buf
int avio_get_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition: aviobuf.c:1398
os_support.h
AV_PKT_FLAG_KEY
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: avcodec.h:1509
AV1SequenceParameters::chroma_subsampling_y
uint8_t chroma_subsampling_y
Definition: av1.h:35
hlsplaylist.h
add_adaptation_set
static int add_adaptation_set(AVFormatContext *s, AdaptationSet **as, enum AVMediaType type)
Definition: dashenc.c:800
DASHContext
Definition: dashdec.c:122
mem
int mem
Definition: avisynth_c.h:916
av_guess_format
ff_const59 AVOutputFormat * av_guess_format(const char *short_name, const char *filename, const char *mime_type)
Return the output format in the list of registered output formats which best matches the provided par...
Definition: format.c:51
AVFormatContext::interrupt_callback
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition: avformat.h:1620
SEGMENT_TYPE_AUTO
@ SEGMENT_TYPE_AUTO
Definition: dashenc.c:54
avio_open2
int avio_open2(AVIOContext **s, const char *url, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options)
Create and initialize a AVIOContext for accessing the resource indicated by url.
Definition: aviobuf.c:1179
DASHContext::single_file_name
const char * single_file_name
Definition: dashenc.c:130
ff_hls_write_playlist_header
void ff_hls_write_playlist_header(AVIOContext *out, int version, int allowcache, int target_duration, int64_t sequence, uint32_t playlist_type, int iframe_mode)
Definition: hlsplaylist.c:77
av_strerror
int av_strerror(int errnum, char *errbuf, size_t errbuf_size)
Put a description of the AVERROR code errnum in errbuf.
Definition: error.c:105
OutputStream::full_path
char full_path[1024]
Definition: dashenc.c:101
dashenc_delete_media_segments
static void dashenc_delete_media_segments(AVFormatContext *s, OutputStream *os, int remove_count)
Definition: dashenc.c:1532
DASHContext::method
const char * method
Definition: dashenc.c:134
gmtime_r
#define gmtime_r
Definition: time_internal.h:34
dashenc_delete_segment_file
static int dashenc_delete_segment_file(AVFormatContext *s, const char *file)
Definition: dashenc.c:1504
avio_tell
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:557
format_string::str
const char * str
Definition: dashenc.c:168
AVFMT_AVOID_NEG_TS_MAKE_ZERO
#define AVFMT_AVOID_NEG_TS_MAKE_ZERO
Shift timestamps so that they start at 0.
Definition: avformat.h:1676
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
add_segment
static int add_segment(OutputStream *os, const char *file, int64_t time, int64_t duration, int64_t start_pos, int64_t range_length, int64_t index_length, int next_exp_index)
Definition: dashenc.c:1379
AVRational::num
int num
Numerator.
Definition: rational.h:59
src
#define src
Definition: vp8dsp.c:254
DASHContext::user_agent
const char * user_agent
Definition: dashenc.c:135
vpcc.h
AV1SequenceParameters::color_description_present_flag
uint8_t color_description_present_flag
Definition: av1.h:37
ff_hls_write_audio_rendition
void ff_hls_write_audio_rendition(AVIOContext *out, char *agroup, char *filename, char *language, int name_id, int is_default)
Definition: hlsplaylist.c:38
get_hls_playlist_name
static void get_hls_playlist_name(char *playlist_name, int string_size, const char *base_url, int id)
Definition: dashenc.c:448
write_time
static void write_time(AVIOContext *out, int64_t time)
Definition: dashenc.c:712
avio_close_dyn_buf
int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition: aviobuf.c:1415
avassert.h
lrint
#define lrint
Definition: tablegen.h:53
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
state
static struct @313 state
buf
void * buf
Definition: avisynth_c.h:766
E
#define E
Definition: dashenc.c:1891
AVCodecTag
Definition: internal.h:44
DASHContext::init_seg_name
const char * init_seg_name
Definition: dashenc.c:131
get_start_index_number
static void get_start_index_number(OutputStream *os, DASHContext *c, int *start_index, int *start_number)
Definition: dashenc.c:456
ff_write_chained
int ff_write_chained(AVFormatContext *dst, int dst_stream, AVPacket *pkt, AVFormatContext *src, int interleave)
Write a packet to another muxer than the one the user originally intended.
Definition: mux.c:1318
duration
int64_t duration
Definition: movenc.c:63
av_dict_get
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition: dict.c:40
avio_open_dyn_buf
int avio_open_dyn_buf(AVIOContext **s)
Open a write only memory stream.
Definition: aviobuf.c:1386
format_string::segment_type
SegmentType segment_type
Definition: dashenc.c:167
intreadwrite.h
s
#define s(width, name)
Definition: cbs_vp9.c:257
DASHContext::ignore_io_errors
int ignore_io_errors
Definition: dashenc.c:147
SegmentType
SegmentType
Definition: dashenc.c:53
AV_OPT_FLAG_ENCODING_PARAM
#define AV_OPT_FLAG_ENCODING_PARAM
a generic parameter which can be set by the user for muxing or encoding
Definition: opt.h:276
avpriv_io_move
int avpriv_io_move(const char *url_src, const char *url_dst)
Move or rename a resource.
Definition: avio.c:502
AVFormatContext::flags
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1473
DASHContext::media_seg_name
const char * media_seg_name
Definition: dashenc.c:132
DASHContext::window_size
int window_size
Definition: dashenc.c:113
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
AV_CODEC_ID_VP9
@ AV_CODEC_ID_VP9
Definition: avcodec.h:386
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
dash_check_bitstream
static int dash_check_bitstream(struct AVFormatContext *s, const AVPacket *avpkt)
Definition: dashenc.c:1867
AVIO_FLAG_WRITE
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:655
AV1SequenceParameters::color_range
uint8_t color_range
Definition: av1.h:41
format_date_now
static void format_date_now(char *buf, int size)
Definition: dashenc.c:728
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
ctx
AVFormatContext * ctx
Definition: movenc.c:48
ff_is_http_proto
int ff_is_http_proto(char *filename)
Utility function to check if the file uses http or https protocol.
Definition: utils.c:5672
OutputStream::max_pts
int64_t max_pts
Definition: dashenc.c:88
DASHContext::use_timeline
int use_timeline
Definition: dashenc.c:121
av_rescale_q
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
DASHContext::hls_playlist
int hls_playlist
Definition: dashenc.c:136
DASHContext::mpd_out
AVIOContext * mpd_out
Definition: dashenc.c:139
AVFormatContext::opaque
void * opaque
User data.
Definition: avformat.h:1848
key
const char * key
Definition: hwcontext_opencl.c:168
dashenc_delete_file
static void dashenc_delete_file(AVFormatContext *s, char *filename)
Definition: dashenc.c:1477
DASHContext::dirname
char dirname[1024]
Definition: dashenc.c:129
OutputStream::media_seg_name
const char * media_seg_name
Definition: dashenc.c:96
write_manifest
static int write_manifest(AVFormatContext *s, int final)
Definition: dashenc.c:934
ff_dash_muxer
AVOutputFormat ff_dash_muxer
Definition: dashenc.c:1934
AV_CODEC_ID_H264
@ AV_CODEC_ID_H264
Definition: avcodec.h:245
avformat_write_header
av_warn_unused_result int avformat_write_header(AVFormatContext *s, AVDictionary **options)
Allocate the stream private data and write the stream header to an output media file.
Definition: mux.c:508
av_packet_get_side_data
uint8_t * av_packet_get_side_data(const AVPacket *pkt, enum AVPacketSideDataType type, int *size)
Get side information from packet.
Definition: avpacket.c:350
time_internal.h
ff_http_do_new_request
int ff_http_do_new_request(URLContext *h, const char *uri)
Send a new HTTP request, reusing the old connection.
Definition: http.c:308
if
if(ret)
Definition: filter_design.txt:179
AVFormatContext
Format I/O context.
Definition: avformat.h:1342
AVStreamInternal::bsfcs
AVBSFContext ** bsfcs
bitstream filters to run on stream
Definition: internal.h:161
DASHContext::streaming
int streaming
Definition: dashenc.c:141
internal.h
opts
AVDictionary * opts
Definition: movenc.c:50
AV1SequenceParameters::chroma_sample_position
uint8_t chroma_sample_position
Definition: av1.h:36
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1017
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:67
AVStream::time_base
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition: avformat.h:899
NULL
#define NULL
Definition: coverity.c:32
SEGMENT_TYPE_WEBM
@ SEGMENT_TYPE_WEBM
Definition: dashenc.c:56
OutputStream::ctx_inited
int ctx_inited
Definition: dashenc.c:80
dash_write_packet
static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
Definition: dashenc.c:1679
isom.h
VPCC::bitdepth
int bitdepth
Definition: vpcc.h:38
DASHContext::use_template
int use_template
Definition: dashenc.c:120
write_trailer
static int write_trailer(AVFormatContext *s1)
Definition: v4l2enc.c:94
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
av_strireplace
char * av_strireplace(const char *str, const char *from, const char *to)
Locale-independent strings replace.
Definition: avstring.c:235
OutputStream::init_start_pos
int64_t init_start_pos
Definition: dashenc.c:84
OutputStream::pos
int64_t pos
Definition: dashenc.c:84
Segment::range_length
int range_length
Definition: dashenc.c:63
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:191
ffurl_shutdown
int ffurl_shutdown(URLContext *h, int flags)
Signal the URLContext that we are done reading or writing the stream.
Definition: avio.c:660
AVFormatContext::pb
AVIOContext * pb
I/O context.
Definition: avformat.h:1384
AV1SequenceParameters::transfer_characteristics
uint8_t transfer_characteristics
Definition: av1.h:39
avc.h
DASHContext::single_file
int single_file
Definition: dashenc.c:122
flush_init_segment
static int flush_init_segment(AVFormatContext *s, OutputStream *os)
Definition: dashenc.c:547
AV1SequenceParameters::tier
uint8_t tier
Definition: av1.h:31
select_segment_type
static SegmentType select_segment_type(SegmentType segment_type, enum AVCodecID codec_id)
Definition: dashenc.c:241
AV_DICT_DONT_OVERWRITE
#define AV_DICT_DONT_OVERWRITE
Don't overwrite existing entries.
Definition: dict.h:76
time.h
DASHContext::start_time_s
time_t start_time_s
Definition: dashenc.c:128
av_write_frame
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file.
Definition: mux.c:878
format_string
Definition: dashenc.c:166
codec_string::id
int id
Definition: dashenc.c:155
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
AVFormatContext::oformat
ff_const59 struct AVOutputFormat * oformat
The output container format.
Definition: avformat.h:1361
AVCodecID
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: avcodec.h:215
DASHContext::lhls
int lhls
Definition: dashenc.c:148
AVCodecParameters::extradata_size
int extradata_size
Size of the extradata content in bytes.
Definition: avcodec.h:3975
AV_CODEC_ID_AAC
@ AV_CODEC_ID_AAC
Definition: avcodec.h:566
ff_codec_movvideo_tags
const AVCodecTag ff_codec_movvideo_tags[]
Definition: isom.c:75
DASHContext::master_publish_rate
int master_publish_rate
Definition: dashenc.c:149
AV1SequenceParameters::monochrome
uint8_t monochrome
Definition: av1.h:33
ff_hls_write_playlist_version
void ff_hls_write_playlist_version(AVIOContext *out, int version)
Definition: hlsplaylist.c:31
OutputStream::extension_name
const char * extension_name
Definition: dashenc.c:93
AVIOContext
Bytestream IO Context.
Definition: avio.h:161
AV1SequenceParameters::matrix_coefficients
uint8_t matrix_coefficients
Definition: av1.h:40
AVMediaType
AVMediaType
Definition: avutil.h:199
AVPacket::size
int size
Definition: avcodec.h:1478
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:188
OutputStream::total_pkt_size
int total_pkt_size
Definition: dashenc.c:104
avformat_alloc_context
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
Definition: options.c:144
OutputStream::availability_time_offset
double availability_time_offset
Definition: dashenc.c:103
av_codec_get_tag
unsigned int av_codec_get_tag(const struct AVCodecTag *const *tags, enum AVCodecID id)
Get the codec tag for the given codec id id.
ff_isom_write_avcc
int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len)
Definition: avc.c:108
FF_COMPLIANCE_STRICT
#define FF_COMPLIANCE_STRICT
Strictly conform to all the things in the spec no matter what consequences.
Definition: avcodec.h:2630
start_time
static int64_t start_time
Definition: ffplay.c:331
FFMAX
#define FFMAX(a, b)
Definition: common.h:94
DASHContext::streams
OutputStream * streams
Definition: dashenc.c:123
AVFormatContext::url
char * url
input or output URL.
Definition: avformat.h:1438
DASHContext::nr_of_streams_to_flush
int nr_of_streams_to_flush
Definition: dashenc.c:150
size
int size
Definition: twinvq_data.h:11134
DASHContext::utc_timing_url
const char * utc_timing_url
Definition: dashenc.c:133
av_reallocp
int av_reallocp(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory through a pointer to a pointer.
Definition: mem.c:163
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
AV_RB32
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_RB32
Definition: bytestream.h:92
AV_CODEC_ID_OPUS
@ AV_CODEC_ID_OPUS
Definition: avcodec.h:624
AVFMT_NOFILE
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:463
DASHContext::has_video
int has_video
Definition: dashenc.c:124
AVMEDIA_TYPE_UNKNOWN
@ AVMEDIA_TYPE_UNKNOWN
Usually treated as AVMEDIA_TYPE_DATA.
Definition: avutil.h:200
AVStream::sample_aspect_ratio
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition: avformat.h:932
SegmentType
SegmentType
Definition: pgssubdec.c:41
Segment::prog_date_time
double prog_date_time
Definition: dashenc.c:65
set_vp9_codec_str
static void set_vp9_codec_str(AVFormatContext *s, AVCodecParameters *par, AVRational *frame_rate, char *str, int size)
Definition: dashenc.c:296
DASHContext::availability_start_time
uint64_t availability_start_time
Definition: dashdec.c:136
avpriv_io_delete
int avpriv_io_delete(const char *url)
Delete a resource.
Definition: avio.c:524
AVPacket::dts
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition: avcodec.h:1476
avio_write
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:218
avio_wb32
void avio_wb32(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:377
OutputStream::segments
Segment ** segments
Definition: dashenc.c:87
DASHContext::nb_as
int nb_as
Definition: dashenc.c:112
AVPacket::flags
int flags
A combination of AV_PKT_FLAG values.
Definition: avcodec.h:1483
av_dict_free
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition: dict.c:203
av_strstart
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
Definition: avstring.c:34
OFFSET
#define OFFSET(x)
Definition: dashenc.c:1890
bitrate
int64_t bitrate
Definition: h264_levels.c:131
OutputStream::temp_path
char temp_path[1024]
Definition: dashenc.c:102
AV1SequenceParameters::profile
uint8_t profile
Definition: av1.h:29
Segment::duration
int64_t duration
Definition: dashenc.c:66
OutputStream::written_len
int written_len
Definition: dashenc.c:99
flush_dynbuf
static int flush_dynbuf(DASHContext *c, OutputStream *os, int *range_length)
Definition: dashenc.c:407
OutputStream::codec_str
char codec_str[100]
Definition: dashenc.c:98
OutputStream::first_pts
int64_t first_pts
Definition: ffmpeg.h:455
av_realloc
void * av_realloc(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory.
Definition: mem.c:135
write_packet
static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int unqueue)
Definition: ffmpeg.c:690
OutputStream::segment_index
int segment_index
Definition: dashenc.c:86
AV1SequenceParameters::color_primaries
uint8_t color_primaries
Definition: av1.h:38
get_format_str
static const char * get_format_str(SegmentType segment_type)
Definition: dashenc.c:214
av_write_trailer
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
Definition: mux.c:1254
URLContext
Definition: url.h:38
AVFMT_GLOBALHEADER
#define AVFMT_GLOBALHEADER
Format wants global header.
Definition: avformat.h:466
AVOutputFormat
Definition: avformat.h:495
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:1470
avio_internal.h
AVERROR_MUXER_NOT_FOUND
#define AVERROR_MUXER_NOT_FOUND
Muxer not found.
Definition: error.h:60
AV_TIME_BASE
#define AV_TIME_BASE
Internal time base represented as integer.
Definition: avutil.h:254
OutputStream::last_pts
int64_t last_pts
Definition: dashenc.c:89
find_index_range
static void find_index_range(AVFormatContext *s, const char *full_path, int64_t pos, int *index_length)
Definition: dashenc.c:1429
AdaptationSet
Definition: dashenc.c:70
AV_CODEC_ID_HEVC
@ AV_CODEC_ID_HEVC
Definition: avcodec.h:392
DASHContext::adaptation_sets
char * adaptation_sets
Definition: dashenc.c:110
AVFormatContext::avoid_negative_ts
int avoid_negative_ts
Avoid negative timestamps during muxing.
Definition: avformat.h:1673
AV1SequenceParameters::level
uint8_t level
Definition: av1.h:30
url.h
uint8_t
uint8_t
Definition: audio_convert.c:194
OutputStream::ctx
AVFormatContext * ctx
Definition: dashenc.c:79
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:236
AdaptationSet::ambiguous_frame_rate
int ambiguous_frame_rate
Definition: dashenc.c:75
len
int len
Definition: vorbis_enc_data.h:452
DASHContext::seg_duration
int64_t seg_duration
Definition: dashenc.c:118
AVFMT_TS_NEGATIVE
#define AVFMT_TS_NEGATIVE
Format allows muxing negative timestamps.
Definition: avformat.h:480
av_cmp_q
static int av_cmp_q(AVRational a, AVRational b)
Compare two rationals.
Definition: rational.h:89
Segment
Definition: dashenc.c:60
ff_av1_parse_seq_header
int ff_av1_parse_seq_header(AV1SequenceParameters *seq, const uint8_t *buf, int size)
Parses a Sequence Header from the the provided buffer.
Definition: av1.c:293
tag
uint32_t tag
Definition: movenc.c:1496
ffio_free_dyn_buf
void ffio_free_dyn_buf(AVIOContext **s)
Free a dynamic buffer.
Definition: aviobuf.c:1445
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:870
OutputStream::init_seg_name
const char * init_seg_name
Definition: dashenc.c:95
write_adaptation_set
static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_index, int final)
Definition: dashenc.c:747
avio_seek
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:246
AVClass::class_name
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:72
av_strlcat
size_t av_strlcat(char *dst, const char *src, size_t size)
Append the string src to the string dst, but to a total length of no more than size - 1 bytes,...
Definition: avstring.c:93
av_strnstr
char * av_strnstr(const char *haystack, const char *needle, size_t hay_length)
Locate the first occurrence of the string needle in the string haystack where not more than hay_lengt...
Definition: avstring.c:69
avformat.h
AV_ERROR_MAX_STRING_SIZE
#define AV_ERROR_MAX_STRING_SIZE
Definition: error.h:83
VPCC::level
int level
Definition: vpcc.h:37
adaptation_set_add_stream
static int adaptation_set_add_stream(AVFormatContext *s, int as_idx, int i)
Definition: dashenc.c:817
SEGMENT_TYPE_NB
@ SEGMENT_TYPE_NB
Definition: dashenc.c:57
AV_RL32
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Definition: bytestream.h:88
avio_printf
int avio_printf(AVIOContext *s, const char *fmt,...) av_printf_format(2
OutputStream::single_file_name
const char * single_file_name
Definition: dashenc.c:94
dash_write_header
static int dash_write_header(AVFormatContext *s)
Definition: dashenc.c:1360
write_styp
static void write_styp(AVIOContext *pb)
Definition: dashenc.c:1419
OutputStream::init_range_length
int init_range_length
Definition: dashenc.c:85
DASHContext::nr_of_streams_flushed
int nr_of_streams_flushed
Definition: dashenc.c:151
dashenc_io_open
static int dashenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename, AVDictionary **options)
Definition: dashenc.c:176
VPCC
Definition: vpcc.h:35
get_extension_str
static const char * get_extension_str(SegmentType type, int single_file)
Definition: dashenc.c:222
Segment::file
char file[1024]
Definition: dashenc.c:61
pkt
static AVPacket pkt
Definition: demuxing_decoding.c:54
OutputStream::initfile
char initfile[1024]
Definition: dashenc.c:83
Segment::index_length
int index_length
Definition: dashenc.c:63
buffer
the frame and frame reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFrame structures Several references can point to the same frame buffer
Definition: filter_design.txt:49
OutputStream::muxer_overhead
int muxer_overhead
Definition: dashenc.c:105
AV_PKT_DATA_NEW_EXTRADATA
@ AV_PKT_DATA_NEW_EXTRADATA
The AV_PKT_DATA_NEW_EXTRADATA is used to notify the codec or the format that the extradata buffer was...
Definition: avcodec.h:1199
AVRational::den
int den
Denominator.
Definition: rational.h:60
config.h
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:223
ff_hls_write_file_entry
int ff_hls_write_file_entry(AVIOContext *out, int insert_discont, int byterange_mode, double duration, int round_duration, int64_t size, int64_t pos, char *baseurl, char *filename, double *prog_date_time, int64_t video_keyframe_size, int64_t video_keyframe_pos, int iframe_mode)
Definition: hlsplaylist.c:109
avformat_free_context
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition: utils.c:4414
av_dict_parse_string
int av_dict_parse_string(AVDictionary **pm, const char *str, const char *key_val_sep, const char *pairs_sep, int flags)
Parse the key/value pairs list and add the parsed entries to a dictionary.
Definition: dict.c:180
avio_read
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:647
AVFormatContext::io_close
void(* io_close)(struct AVFormatContext *s, AVIOContext *pb)
A callback for closing the streams opened with AVFormatContext.io_open().
Definition: avformat.h:1930
OutputStream::nb_segments
int nb_segments
Definition: dashenc.c:86
AVFormatContext::io_open
int(* io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags, AVDictionary **options)
A callback for opening new IO streams.
Definition: avformat.h:1924
DASHContext::total_duration
int64_t total_duration
Definition: dashenc.c:126
AV1SequenceParameters::chroma_subsampling_x
uint8_t chroma_subsampling_x
Definition: av1.h:34
dash_write_trailer
static int dash_write_trailer(AVFormatContext *s)
Definition: dashenc.c:1825
AVPacket::stream_index
int stream_index
Definition: avcodec.h:1479
OutputStream::filename
char filename[1024]
Definition: dashenc.c:100
write_hls_media_playlist
static void write_hls_media_playlist(OutputStream *os, AVFormatContext *s, int representation_id, int final, char *prefetch_url)
Definition: dashenc.c:466
OutputStream::out
AVIOContext * out
Definition: dashenc.c:81
OutputStream::bit_rate
int bit_rate
Definition: dashenc.c:90
av_gettime
int64_t av_gettime(void)
Get the current time in microseconds.
Definition: time.c:39
av_dict_set_int
int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags)
Convenience wrapper for av_dict_set that converts the value to a string and stores it.
Definition: dict.c:147
ff_format_io_close
void ff_format_io_close(AVFormatContext *s, AVIOContext **pb)
Definition: utils.c:5665
AVIO_FLAG_READ
#define AVIO_FLAG_READ
read-only
Definition: avio.h:654
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:251
output_segment_list
static void output_segment_list(OutputStream *os, AVIOContext *out, AVFormatContext *s, int representation_id, int final)
Definition: dashenc.c:603
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
avutil.h
DASHContext::m3u8_out
AVIOContext * m3u8_out
Definition: dashenc.c:140
avio_flush
int void avio_flush(AVIOContext *s)
Force flushing of buffered data.
Definition: aviobuf.c:238
handle_io_open_error
static int handle_io_open_error(AVFormatContext *s, int err, char *url)
Definition: dashenc.c:232
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
dash_flush
static int dash_flush(AVFormatContext *s, int final, int stream)
Definition: dashenc.c:1545
AVDictionaryEntry
Definition: dict.h:81
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: avcodec.h:3957
AVPacket
This structure stores compressed data.
Definition: avcodec.h:1454
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:240
ff_dash_fill_tmpl_params
void ff_dash_fill_tmpl_params(char *dst, size_t buffer_size, const char *template, int rep_id, int number, int bit_rate, int64_t time)
Definition: dash.c:96
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
av_dict_set
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition: dict.c:70
avio_find_protocol_name
const char * avio_find_protocol_name(const char *url)
Return the name of the protocol that will handle the passed URL.
Definition: avio.c:476
codec_string
Definition: dashenc.c:154
check_file_extension
static int check_file_extension(const char *filename, const char *extension)
Definition: dashenc.c:286
OutputStream
Definition: muxing.c:53
AV_CODEC_ID_VP8
@ AV_CODEC_ID_VP8
Definition: avcodec.h:358
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:565
av_strlcpy
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
Definition: avstring.c:83
AVCodecParameters::bit_rate
int64_t bit_rate
The average bitrate of the encoded data (in bits per second).
Definition: avcodec.h:3986
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
AV1SequenceParameters::bitdepth
uint8_t bitdepth
Definition: av1.h:32
ff_codec_movaudio_tags
const AVCodecTag ff_codec_movaudio_tags[]
Definition: isom.c:318
dash_class
static const AVClass dash_class
Definition: dashenc.c:1927
av1.h
AV_CODEC_ID_VORBIS
@ AV_CODEC_ID_VORBIS
Definition: avcodec.h:569
dash.h
AV1SequenceParameters
Definition: av1.h:28
AVDictionaryEntry::value
char * value
Definition: dict.h:83
VPCC::profile
int profile
Definition: vpcc.h:36
avstring.h
AVStreamInternal::nb_bsfcs
int nb_bsfcs
Definition: internal.h:162
DASHContext::segment_type_option
SegmentType segment_type_option
Definition: dashenc.c:146
Segment::time
int64_t time
Definition: dashenc.c:64
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:227
write_header
static void write_header(FFV1Context *f)
Definition: ffv1enc.c:337
Segment::start_pos
int64_t start_pos
Definition: dashenc.c:62
http.h
dash_free
static void dash_free(AVFormatContext *s)
Definition: dashenc.c:565
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:232
snprintf
#define snprintf
Definition: snprintf.h:34
OutputStream::segments_size
int segments_size
Definition: dashenc.c:86
ff_hls_write_init_file
void ff_hls_write_init_file(AVIOContext *out, char *filename, int byterange_mode, int64_t size, int64_t pos)
Definition: hlsplaylist.c:100
ffio_geturlcontext
URLContext * ffio_geturlcontext(AVIOContext *s)
Return the URLContext associated with the AVIOContext.
Definition: aviobuf.c:1038
AdaptationSet::media_type
enum AVMediaType media_type
Definition: dashenc.c:72
init_segment_types
static int init_segment_types(AVFormatContext *s)
Definition: dashenc.c:255
avcodec_parameters_copy
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
Copy the contents of src to dst.
Definition: utils.c:2080
DASHContext::extra_window_size
int extra_window_size
Definition: dashenc.c:114
ff_hls_write_stream_info
void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, int bandwidth, char *filename, char *agroup, char *codecs, char *ccgroup)
Definition: hlsplaylist.c:51
AV_RB16
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_WB32 unsigned int_TMPL AV_WB24 unsigned int_TMPL AV_RB16
Definition: bytestream.h:94
xmlescape
static char * xmlescape(const char *str)
Definition: dashenc.c:672
ff_alloc_extradata
int ff_alloc_extradata(AVCodecParameters *par, int size)
Allocate extradata with additional AV_INPUT_BUFFER_PADDING_SIZE at end which is always set to 0.
Definition: utils.c:3309
OutputStream::segment_type
SegmentType segment_type
Definition: dashenc.c:91