FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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"
36 
37 #include "avc.h"
38 #include "avformat.h"
39 #include "avio_internal.h"
40 #include "hlsplaylist.h"
41 #if CONFIG_HTTP_PROTOCOL
42 #include "http.h"
43 #endif
44 #include "internal.h"
45 #include "isom.h"
46 #include "os_support.h"
47 #include "url.h"
48 #include "dash.h"
49 
50 typedef struct Segment {
51  char file[1024];
52  int64_t start_pos;
54  int64_t time;
55  int duration;
56  int n;
57 } Segment;
58 
59 typedef struct AdaptationSet {
60  char id[10];
66 
67 typedef struct OutputStream {
71  char format_name[8];
73  char initfile[1024];
74  int64_t init_start_pos, pos;
79  int64_t last_dts;
80  int bit_rate;
81  char bandwidth_str[64];
82 
83  char codec_str[100];
85  char filename[1024];
86  char full_path[1024];
87  char temp_path[1024];
88 } OutputStream;
89 
90 typedef struct DASHContext {
91  const AVClass *class; /* Class for private options. */
94  int nb_as;
104  int64_t last_duration;
105  int64_t total_duration;
107  char dirname[1024];
108  const char *single_file_name;
109  const char *init_seg_name;
110  const char *media_seg_name;
111  const char *utc_timing_url;
112  const char *method;
113  const char *user_agent;
120  int64_t timeout;
121 } DASHContext;
122 
123 static struct codec_string {
124  int id;
125  const char *str;
126 } codecs[] = {
127  { AV_CODEC_ID_VP8, "vp8" },
128  { AV_CODEC_ID_VP9, "vp9" },
129  { AV_CODEC_ID_VORBIS, "vorbis" },
130  { AV_CODEC_ID_OPUS, "opus" },
131  { 0, NULL }
132 };
133 
134 static int dashenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename,
135  AVDictionary **options) {
136  DASHContext *c = s->priv_data;
137  int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
138  int err = AVERROR_MUXER_NOT_FOUND;
139  if (!*pb || !http_base_proto || !c->http_persistent) {
140  err = s->io_open(s, pb, filename, AVIO_FLAG_WRITE, options);
141 #if CONFIG_HTTP_PROTOCOL
142  } else {
143  URLContext *http_url_context = ffio_geturlcontext(*pb);
144  av_assert0(http_url_context);
145  err = ff_http_do_new_request(http_url_context, filename);
146 #endif
147  }
148  return err;
149 }
150 
151 static void dashenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename) {
152  DASHContext *c = s->priv_data;
153  int http_base_proto = filename ? ff_is_http_proto(filename) : 0;
154 
155  if (!http_base_proto || !c->http_persistent) {
156  ff_format_io_close(s, pb);
157 #if CONFIG_HTTP_PROTOCOL
158  } else {
159  URLContext *http_url_context = ffio_geturlcontext(*pb);
160  av_assert0(http_url_context);
161  avio_flush(*pb);
162  ffurl_shutdown(http_url_context, AVIO_FLAG_WRITE);
163 #endif
164  }
165 }
166 
168  char *str, int size)
169 {
170  const AVCodecTag *tags[2] = { NULL, NULL };
171  uint32_t tag;
172  int i;
173 
174  // common Webm codecs are not part of RFC 6381
175  for (i = 0; codecs[i].id; i++)
176  if (codecs[i].id == par->codec_id) {
177  av_strlcpy(str, codecs[i].str, size);
178  return;
179  }
180 
181  // for codecs part of RFC 6381
182  if (par->codec_type == AVMEDIA_TYPE_VIDEO)
183  tags[0] = ff_codec_movvideo_tags;
184  else if (par->codec_type == AVMEDIA_TYPE_AUDIO)
185  tags[0] = ff_codec_movaudio_tags;
186  else
187  return;
188 
189  tag = av_codec_get_tag(tags, par->codec_id);
190  if (!tag)
191  return;
192  if (size < 5)
193  return;
194 
195  AV_WL32(str, tag);
196  str[4] = '\0';
197  if (!strcmp(str, "mp4a") || !strcmp(str, "mp4v")) {
198  uint32_t oti;
199  tags[0] = ff_mp4_obj_type;
200  oti = av_codec_get_tag(tags, par->codec_id);
201  if (oti)
202  av_strlcatf(str, size, ".%02"PRIx32, oti);
203  else
204  return;
205 
206  if (tag == MKTAG('m', 'p', '4', 'a')) {
207  if (par->extradata_size >= 2) {
208  int aot = par->extradata[0] >> 3;
209  if (aot == 31)
210  aot = ((AV_RB16(par->extradata) >> 5) & 0x3f) + 32;
211  av_strlcatf(str, size, ".%d", aot);
212  }
213  } else if (tag == MKTAG('m', 'p', '4', 'v')) {
214  // Unimplemented, should output ProfileLevelIndication as a decimal number
215  av_log(s, AV_LOG_WARNING, "Incomplete RFC 6381 codec string for mp4v\n");
216  }
217  } else if (!strcmp(str, "avc1")) {
218  uint8_t *tmpbuf = NULL;
219  uint8_t *extradata = par->extradata;
220  int extradata_size = par->extradata_size;
221  if (!extradata_size)
222  return;
223  if (extradata[0] != 1) {
224  AVIOContext *pb;
225  if (avio_open_dyn_buf(&pb) < 0)
226  return;
227  if (ff_isom_write_avcc(pb, extradata, extradata_size) < 0) {
228  ffio_free_dyn_buf(&pb);
229  return;
230  }
231  extradata_size = avio_close_dyn_buf(pb, &extradata);
232  tmpbuf = extradata;
233  }
234 
235  if (extradata_size >= 4)
236  av_strlcatf(str, size, ".%02x%02x%02x",
237  extradata[1], extradata[2], extradata[3]);
238  av_free(tmpbuf);
239  }
240 }
241 
242 static int flush_dynbuf(OutputStream *os, int *range_length)
243 {
244  uint8_t *buffer;
245 
246  if (!os->ctx->pb) {
247  return AVERROR(EINVAL);
248  }
249 
250  // flush
251  av_write_frame(os->ctx, NULL);
252  avio_flush(os->ctx->pb);
253 
254  // write out to file
255  *range_length = avio_close_dyn_buf(os->ctx->pb, &buffer);
256  os->ctx->pb = NULL;
257  avio_write(os->out, buffer + os->written_len, *range_length - os->written_len);
258  os->written_len = 0;
259  av_free(buffer);
260 
261  // re-open buffer
262  return avio_open_dyn_buf(&os->ctx->pb);
263 }
264 
266 {
267  if (c->method)
268  av_dict_set(options, "method", c->method, 0);
269  if (c->user_agent)
270  av_dict_set(options, "user_agent", c->user_agent, 0);
271  if (c->http_persistent)
272  av_dict_set_int(options, "multiple_requests", 1, 0);
273  if (c->timeout >= 0)
274  av_dict_set_int(options, "timeout", c->timeout, 0);
275 }
276 
277 static void get_hls_playlist_name(char *playlist_name, int string_size,
278  const char *base_url, int id) {
279  if (base_url)
280  snprintf(playlist_name, string_size, "%smedia_%d.m3u8", base_url, id);
281  else
282  snprintf(playlist_name, string_size, "media_%d.m3u8", id);
283 }
284 
286 {
287  DASHContext *c = s->priv_data;
288  int ret, range_length;
289 
290  ret = flush_dynbuf(os, &range_length);
291  if (ret < 0)
292  return ret;
293 
294  os->pos = os->init_range_length = range_length;
295  if (!c->single_file)
296  ff_format_io_close(s, &os->out);
297  return 0;
298 }
299 
301 {
302  DASHContext *c = s->priv_data;
303  int i, j;
304 
305  if (c->as) {
306  for (i = 0; i < c->nb_as; i++)
307  av_dict_free(&c->as[i].metadata);
308  av_freep(&c->as);
309  c->nb_as = 0;
310  }
311 
312  if (!c->streams)
313  return;
314  for (i = 0; i < s->nb_streams; i++) {
315  OutputStream *os = &c->streams[i];
316  if (os->ctx && os->ctx_inited)
317  av_write_trailer(os->ctx);
318  if (os->ctx && os->ctx->pb)
319  ffio_free_dyn_buf(&os->ctx->pb);
320  ff_format_io_close(s, &os->out);
321  if (os->ctx)
323  for (j = 0; j < os->nb_segments; j++)
324  av_free(os->segments[j]);
325  av_free(os->segments);
326  }
327  av_freep(&c->streams);
328 
329  ff_format_io_close(s, &c->mpd_out);
331 }
332 
334  int representation_id, int final)
335 {
336  DASHContext *c = s->priv_data;
337  int i, start_index = 0, start_number = 1;
338  if (c->window_size) {
339  start_index = FFMAX(os->nb_segments - c->window_size, 0);
340  start_number = FFMAX(os->segment_index - c->window_size, 1);
341  }
342 
343  if (c->use_template) {
344  int timescale = c->use_timeline ? os->ctx->streams[0]->time_base.den : AV_TIME_BASE;
345  avio_printf(out, "\t\t\t\t<SegmentTemplate timescale=\"%d\" ", timescale);
346  if (!c->use_timeline)
347  avio_printf(out, "duration=\"%"PRId64"\" ", c->last_duration);
348  avio_printf(out, "initialization=\"%s\" media=\"%s\" startNumber=\"%d\">\n", c->init_seg_name, c->media_seg_name, c->use_timeline ? start_number : 1);
349  if (c->use_timeline) {
350  int64_t cur_time = 0;
351  avio_printf(out, "\t\t\t\t\t<SegmentTimeline>\n");
352  for (i = start_index; i < os->nb_segments; ) {
353  Segment *seg = os->segments[i];
354  int repeat = 0;
355  avio_printf(out, "\t\t\t\t\t\t<S ");
356  if (i == start_index || seg->time != cur_time) {
357  cur_time = seg->time;
358  avio_printf(out, "t=\"%"PRId64"\" ", seg->time);
359  }
360  avio_printf(out, "d=\"%d\" ", seg->duration);
361  while (i + repeat + 1 < os->nb_segments &&
362  os->segments[i + repeat + 1]->duration == seg->duration &&
363  os->segments[i + repeat + 1]->time == os->segments[i + repeat]->time + os->segments[i + repeat]->duration)
364  repeat++;
365  if (repeat > 0)
366  avio_printf(out, "r=\"%d\" ", repeat);
367  avio_printf(out, "/>\n");
368  i += 1 + repeat;
369  cur_time += (1 + repeat) * seg->duration;
370  }
371  avio_printf(out, "\t\t\t\t\t</SegmentTimeline>\n");
372  }
373  avio_printf(out, "\t\t\t\t</SegmentTemplate>\n");
374  } else if (c->single_file) {
375  avio_printf(out, "\t\t\t\t<BaseURL>%s</BaseURL>\n", os->initfile);
376  avio_printf(out, "\t\t\t\t<SegmentList timescale=\"%d\" duration=\"%"PRId64"\" startNumber=\"%d\">\n", AV_TIME_BASE, c->last_duration, start_number);
377  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);
378  for (i = start_index; i < os->nb_segments; i++) {
379  Segment *seg = os->segments[i];
380  avio_printf(out, "\t\t\t\t\t<SegmentURL mediaRange=\"%"PRId64"-%"PRId64"\" ", seg->start_pos, seg->start_pos + seg->range_length - 1);
381  if (seg->index_length)
382  avio_printf(out, "indexRange=\"%"PRId64"-%"PRId64"\" ", seg->start_pos, seg->start_pos + seg->index_length - 1);
383  avio_printf(out, "/>\n");
384  }
385  avio_printf(out, "\t\t\t\t</SegmentList>\n");
386  } else {
387  avio_printf(out, "\t\t\t\t<SegmentList timescale=\"%d\" duration=\"%"PRId64"\" startNumber=\"%d\">\n", AV_TIME_BASE, c->last_duration, start_number);
388  avio_printf(out, "\t\t\t\t\t<Initialization sourceURL=\"%s\" />\n", os->initfile);
389  for (i = start_index; i < os->nb_segments; i++) {
390  Segment *seg = os->segments[i];
391  avio_printf(out, "\t\t\t\t\t<SegmentURL media=\"%s\" />\n", seg->file);
392  }
393  avio_printf(out, "\t\t\t\t</SegmentList>\n");
394  }
395  if (c->hls_playlist && start_index < os->nb_segments)
396  {
397  int timescale = os->ctx->streams[0]->time_base.den;
398  char temp_filename_hls[1024];
399  char filename_hls[1024];
400  AVDictionary *http_opts = NULL;
401  int target_duration = 0;
402  int ret = 0;
403  const char *proto = avio_find_protocol_name(c->dirname);
404  int use_rename = proto && !strcmp(proto, "file");
405 
406  get_hls_playlist_name(filename_hls, sizeof(filename_hls),
407  c->dirname, representation_id);
408 
409  snprintf(temp_filename_hls, sizeof(temp_filename_hls), use_rename ? "%s.tmp" : "%s", filename_hls);
410 
411  set_http_options(&http_opts, c);
412  dashenc_io_open(s, &c->m3u8_out, temp_filename_hls, &http_opts);
413  av_dict_free(&http_opts);
414  for (i = start_index; i < os->nb_segments; i++) {
415  Segment *seg = os->segments[i];
416  double duration = (double) seg->duration / timescale;
417  if (target_duration <= duration)
418  target_duration = lrint(duration);
419  }
420 
421  ff_hls_write_playlist_header(c->m3u8_out, 6, -1, target_duration,
422  start_number, PLAYLIST_TYPE_NONE);
423 
426 
427  for (i = start_index; i < os->nb_segments; i++) {
428  Segment *seg = os->segments[i];
430  (double) seg->duration / timescale, 0,
431  seg->range_length, seg->start_pos, NULL,
432  c->single_file ? os->initfile : seg->file,
433  NULL);
434  if (ret < 0) {
435  av_log(os->ctx, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n");
436  }
437  }
438 
439  if (final)
441 
442  dashenc_io_close(s, &c->m3u8_out, temp_filename_hls);
443 
444  if (use_rename)
445  if (avpriv_io_move(temp_filename_hls, filename_hls) < 0) {
446  av_log(os->ctx, AV_LOG_WARNING, "renaming file %s to %s failed\n\n", temp_filename_hls, filename_hls);
447  }
448  }
449 
450 }
451 
452 static char *xmlescape(const char *str) {
453  int outlen = strlen(str)*3/2 + 6;
454  char *out = av_realloc(NULL, outlen + 1);
455  int pos = 0;
456  if (!out)
457  return NULL;
458  for (; *str; str++) {
459  if (pos + 6 > outlen) {
460  char *tmp;
461  outlen = 2 * outlen + 6;
462  tmp = av_realloc(out, outlen + 1);
463  if (!tmp) {
464  av_free(out);
465  return NULL;
466  }
467  out = tmp;
468  }
469  if (*str == '&') {
470  memcpy(&out[pos], "&amp;", 5);
471  pos += 5;
472  } else if (*str == '<') {
473  memcpy(&out[pos], "&lt;", 4);
474  pos += 4;
475  } else if (*str == '>') {
476  memcpy(&out[pos], "&gt;", 4);
477  pos += 4;
478  } else if (*str == '\'') {
479  memcpy(&out[pos], "&apos;", 6);
480  pos += 6;
481  } else if (*str == '\"') {
482  memcpy(&out[pos], "&quot;", 6);
483  pos += 6;
484  } else {
485  out[pos++] = *str;
486  }
487  }
488  out[pos] = '\0';
489  return out;
490 }
491 
492 static void write_time(AVIOContext *out, int64_t time)
493 {
494  int seconds = time / AV_TIME_BASE;
495  int fractions = time % AV_TIME_BASE;
496  int minutes = seconds / 60;
497  int hours = minutes / 60;
498  seconds %= 60;
499  minutes %= 60;
500  avio_printf(out, "PT");
501  if (hours)
502  avio_printf(out, "%dH", hours);
503  if (hours || minutes)
504  avio_printf(out, "%dM", minutes);
505  avio_printf(out, "%d.%dS", seconds, fractions / (AV_TIME_BASE / 10));
506 }
507 
508 static void format_date_now(char *buf, int size)
509 {
510  time_t t = time(NULL);
511  struct tm *ptm, tmbuf;
512  ptm = gmtime_r(&t, &tmbuf);
513  if (ptm) {
514  if (!strftime(buf, size, "%Y-%m-%dT%H:%M:%SZ", ptm))
515  buf[0] = '\0';
516  }
517 }
518 
520  int final)
521 {
522  DASHContext *c = s->priv_data;
523  AdaptationSet *as = &c->as[as_index];
524  AVDictionaryEntry *lang, *role;
525  int i;
526 
527  avio_printf(out, "\t\t<AdaptationSet id=\"%s\" contentType=\"%s\" segmentAlignment=\"true\" bitstreamSwitching=\"true\"",
528  as->id, as->media_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio");
530  avio_printf(out, " maxFrameRate=\"%d/%d\"", as->max_frame_rate.num, as->max_frame_rate.den);
531  lang = av_dict_get(as->metadata, "language", NULL, 0);
532  if (lang)
533  avio_printf(out, " lang=\"%s\"", lang->value);
534  avio_printf(out, ">\n");
535 
536  role = av_dict_get(as->metadata, "role", NULL, 0);
537  if (role)
538  avio_printf(out, "\t\t\t<Role schemeIdUri=\"urn:mpeg:dash:role:2011\" value=\"%s\"/>\n", role->value);
539 
540  for (i = 0; i < s->nb_streams; i++) {
541  OutputStream *os = &c->streams[i];
542 
543  if (os->as_idx - 1 != as_index)
544  continue;
545 
546  if (as->media_type == AVMEDIA_TYPE_VIDEO) {
547  AVStream *st = s->streams[i];
548  avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"video/%s\" codecs=\"%s\"%s width=\"%d\" height=\"%d\"",
549  i, os->format_name, os->codec_str, os->bandwidth_str, s->streams[i]->codecpar->width, s->streams[i]->codecpar->height);
550  if (st->avg_frame_rate.num)
551  avio_printf(out, " frameRate=\"%d/%d\"", st->avg_frame_rate.num, st->avg_frame_rate.den);
552  avio_printf(out, ">\n");
553  } else {
554  avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"audio/%s\" codecs=\"%s\"%s audioSamplingRate=\"%d\">\n",
555  i, os->format_name, os->codec_str, os->bandwidth_str, s->streams[i]->codecpar->sample_rate);
556  avio_printf(out, "\t\t\t\t<AudioChannelConfiguration schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\" value=\"%d\" />\n",
557  s->streams[i]->codecpar->channels);
558  }
559  output_segment_list(os, out, s, i, final);
560  avio_printf(out, "\t\t\t</Representation>\n");
561  }
562  avio_printf(out, "\t\t</AdaptationSet>\n");
563 
564  return 0;
565 }
566 
568 {
569  DASHContext *c = s->priv_data;
570 
571  void *mem = av_realloc(c->as, sizeof(*c->as) * (c->nb_as + 1));
572  if (!mem)
573  return AVERROR(ENOMEM);
574  c->as = mem;
575  ++c->nb_as;
576 
577  *as = &c->as[c->nb_as - 1];
578  memset(*as, 0, sizeof(**as));
579  (*as)->media_type = type;
580 
581  return 0;
582 }
583 
584 static int adaptation_set_add_stream(AVFormatContext *s, int as_idx, int i)
585 {
586  DASHContext *c = s->priv_data;
587  AdaptationSet *as = &c->as[as_idx - 1];
588  OutputStream *os = &c->streams[i];
589 
590  if (as->media_type != s->streams[i]->codecpar->codec_type) {
591  av_log(s, AV_LOG_ERROR, "Codec type of stream %d doesn't match AdaptationSet's media type\n", i);
592  return AVERROR(EINVAL);
593  } else if (os->as_idx) {
594  av_log(s, AV_LOG_ERROR, "Stream %d is already assigned to an AdaptationSet\n", i);
595  return AVERROR(EINVAL);
596  }
597  os->as_idx = as_idx;
598 
599  return 0;
600 }
601 
603 {
604  DASHContext *c = s->priv_data;
605  const char *p = c->adaptation_sets;
606  enum { new_set, parse_id, parsing_streams } state;
607  AdaptationSet *as;
608  int i, n, ret;
609 
610  // default: one AdaptationSet for each stream
611  if (!p) {
612  for (i = 0; i < s->nb_streams; i++) {
613  if ((ret = add_adaptation_set(s, &as, s->streams[i]->codecpar->codec_type)) < 0)
614  return ret;
615  snprintf(as->id, sizeof(as->id), "%d", i);
616 
617  c->streams[i].as_idx = c->nb_as;
618  }
619  goto end;
620  }
621 
622  // syntax id=0,streams=0,1,2 id=1,streams=3,4 and so on
623  state = new_set;
624  while (*p) {
625  if (*p == ' ') {
626  p++;
627  continue;
628  } else if (state == new_set && av_strstart(p, "id=", &p)) {
629 
630  if ((ret = add_adaptation_set(s, &as, AVMEDIA_TYPE_UNKNOWN)) < 0)
631  return ret;
632 
633  n = strcspn(p, ",");
634  snprintf(as->id, sizeof(as->id), "%.*s", n, p);
635 
636  p += n;
637  if (*p)
638  p++;
639  state = parse_id;
640  } else if (state == parse_id && av_strstart(p, "streams=", &p)) {
641  state = parsing_streams;
642  } else if (state == parsing_streams) {
643  AdaptationSet *as = &c->as[c->nb_as - 1];
644  char idx_str[8], *end_str;
645 
646  n = strcspn(p, " ,");
647  snprintf(idx_str, sizeof(idx_str), "%.*s", n, p);
648  p += n;
649 
650  // if value is "a" or "v", map all streams of that type
651  if (as->media_type == AVMEDIA_TYPE_UNKNOWN && (idx_str[0] == 'v' || idx_str[0] == 'a')) {
652  enum AVMediaType type = (idx_str[0] == 'v') ? AVMEDIA_TYPE_VIDEO : AVMEDIA_TYPE_AUDIO;
653  av_log(s, AV_LOG_DEBUG, "Map all streams of type %s\n", idx_str);
654 
655  for (i = 0; i < s->nb_streams; i++) {
656  if (s->streams[i]->codecpar->codec_type != type)
657  continue;
658 
659  as->media_type = s->streams[i]->codecpar->codec_type;
660 
661  if ((ret = adaptation_set_add_stream(s, c->nb_as, i)) < 0)
662  return ret;
663  }
664  } else { // select single stream
665  i = strtol(idx_str, &end_str, 10);
666  if (idx_str == end_str || i < 0 || i >= s->nb_streams) {
667  av_log(s, AV_LOG_ERROR, "Selected stream \"%s\" not found!\n", idx_str);
668  return AVERROR(EINVAL);
669  }
670  av_log(s, AV_LOG_DEBUG, "Map stream %d\n", i);
671 
672  if (as->media_type == AVMEDIA_TYPE_UNKNOWN) {
673  as->media_type = s->streams[i]->codecpar->codec_type;
674  }
675 
676  if ((ret = adaptation_set_add_stream(s, c->nb_as, i)) < 0)
677  return ret;
678  }
679 
680  if (*p == ' ')
681  state = new_set;
682  if (*p)
683  p++;
684  } else {
685  return AVERROR(EINVAL);
686  }
687  }
688 
689 end:
690  // check for unassigned streams
691  for (i = 0; i < s->nb_streams; i++) {
692  OutputStream *os = &c->streams[i];
693  if (!os->as_idx) {
694  av_log(s, AV_LOG_ERROR, "Stream %d is not mapped to an AdaptationSet\n", i);
695  return AVERROR(EINVAL);
696  }
697  }
698  return 0;
699 }
700 
701 static int write_manifest(AVFormatContext *s, int final)
702 {
703  DASHContext *c = s->priv_data;
704  AVIOContext *out;
705  char temp_filename[1024];
706  int ret, i;
707  const char *proto = avio_find_protocol_name(s->url);
708  int use_rename = proto && !strcmp(proto, "file");
709  static unsigned int warned_non_file = 0;
710  AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
712 
713  if (!use_rename && !warned_non_file++)
714  av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this may lead to races and temporary partial files\n");
715 
716  snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", s->url);
717  set_http_options(&opts, c);
718  ret = dashenc_io_open(s, &c->mpd_out, temp_filename, &opts);
719  if (ret < 0) {
720  av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
721  return ret;
722  }
723  out = c->mpd_out;
724  av_dict_free(&opts);
725  avio_printf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
726  avio_printf(out, "<MPD xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
727  "\txmlns=\"urn:mpeg:dash:schema:mpd:2011\"\n"
728  "\txmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
729  "\txsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd\"\n"
730  "\tprofiles=\"urn:mpeg:dash:profile:isoff-live:2011\"\n"
731  "\ttype=\"%s\"\n", final ? "static" : "dynamic");
732  if (final) {
733  avio_printf(out, "\tmediaPresentationDuration=\"");
734  write_time(out, c->total_duration);
735  avio_printf(out, "\"\n");
736  } else {
737  int64_t update_period = c->last_duration / AV_TIME_BASE;
738  char now_str[100];
739  if (c->use_template && !c->use_timeline)
740  update_period = 500;
741  avio_printf(out, "\tminimumUpdatePeriod=\"PT%"PRId64"S\"\n", update_period);
742  avio_printf(out, "\tsuggestedPresentationDelay=\"PT%"PRId64"S\"\n", c->last_duration / AV_TIME_BASE);
743  if (!c->availability_start_time[0] && s->nb_streams > 0 && c->streams[0].nb_segments > 0) {
745  }
746  if (c->availability_start_time[0])
747  avio_printf(out, "\tavailabilityStartTime=\"%s\"\n", c->availability_start_time);
748  format_date_now(now_str, sizeof(now_str));
749  if (now_str[0])
750  avio_printf(out, "\tpublishTime=\"%s\"\n", now_str);
751  if (c->window_size && c->use_template) {
752  avio_printf(out, "\ttimeShiftBufferDepth=\"");
753  write_time(out, c->last_duration * c->window_size);
754  avio_printf(out, "\"\n");
755  }
756  }
757  avio_printf(out, "\tminBufferTime=\"");
758  write_time(out, c->last_duration * 2);
759  avio_printf(out, "\">\n");
760  avio_printf(out, "\t<ProgramInformation>\n");
761  if (title) {
762  char *escaped = xmlescape(title->value);
763  avio_printf(out, "\t\t<Title>%s</Title>\n", escaped);
764  av_free(escaped);
765  }
766  avio_printf(out, "\t</ProgramInformation>\n");
767 
768  if (c->window_size && s->nb_streams > 0 && c->streams[0].nb_segments > 0 && !c->use_template) {
769  OutputStream *os = &c->streams[0];
770  int start_index = FFMAX(os->nb_segments - c->window_size, 0);
771  int64_t start_time = av_rescale_q(os->segments[start_index]->time, s->streams[0]->time_base, AV_TIME_BASE_Q);
772  avio_printf(out, "\t<Period id=\"0\" start=\"");
773  write_time(out, start_time);
774  avio_printf(out, "\">\n");
775  } else {
776  avio_printf(out, "\t<Period id=\"0\" start=\"PT0.0S\">\n");
777  }
778 
779  for (i = 0; i < c->nb_as; i++) {
780  if ((ret = write_adaptation_set(s, out, i, final)) < 0)
781  return ret;
782  }
783  avio_printf(out, "\t</Period>\n");
784 
785  if (c->utc_timing_url)
786  avio_printf(out, "\t<UTCTiming schemeIdUri=\"urn:mpeg:dash:utc:http-xsdate:2014\" value=\"%s\"/>\n", c->utc_timing_url);
787 
788  avio_printf(out, "</MPD>\n");
789  avio_flush(out);
790  dashenc_io_close(s, &c->mpd_out, temp_filename);
791 
792  if (use_rename) {
793  if ((ret = avpriv_io_move(temp_filename, s->url)) < 0)
794  return ret;
795  }
796 
797  if (c->hls_playlist && !c->master_playlist_created) {
798  char filename_hls[1024];
799  const char *audio_group = "A1";
800  int is_default = 1;
801  int max_audio_bitrate = 0;
802 
803  if (*c->dirname)
804  snprintf(filename_hls, sizeof(filename_hls), "%s/master.m3u8", c->dirname);
805  else
806  snprintf(filename_hls, sizeof(filename_hls), "master.m3u8");
807 
808  snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", filename_hls);
809 
810  set_http_options(&opts, c);
811  ret = avio_open2(&out, temp_filename, AVIO_FLAG_WRITE, NULL, &opts);
812  if (ret < 0) {
813  av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
814  return ret;
815  }
816  av_dict_free(&opts);
817 
819 
820  for (i = 0; i < s->nb_streams; i++) {
821  char playlist_file[64];
822  AVStream *st = s->streams[i];
824  continue;
825  get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, i);
826  ff_hls_write_audio_rendition(out, (char *)audio_group,
827  playlist_file, i, is_default);
828  max_audio_bitrate = FFMAX(st->codecpar->bit_rate, max_audio_bitrate);
829  is_default = 0;
830  }
831 
832  for (i = 0; i < s->nb_streams; i++) {
833  char playlist_file[64];
834  AVStream *st = s->streams[i];
835  char *agroup = NULL;
836  int stream_bitrate = st->codecpar->bit_rate;
837  if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) && max_audio_bitrate) {
838  agroup = (char *)audio_group;
839  stream_bitrate += max_audio_bitrate;
840  }
841  get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, i);
842  ff_hls_write_stream_info(st, out, stream_bitrate, playlist_file, agroup, NULL, NULL);
843  }
844  avio_close(out);
845  if (use_rename)
846  if ((ret = avpriv_io_move(temp_filename, filename_hls)) < 0)
847  return ret;
849  }
850 
851  return 0;
852 }
853 
854 static int dict_copy_entry(AVDictionary **dst, const AVDictionary *src, const char *key)
855 {
856  AVDictionaryEntry *entry = av_dict_get(src, key, NULL, 0);
857  if (entry)
858  av_dict_set(dst, key, entry->value, AV_DICT_DONT_OVERWRITE);
859  return 0;
860 }
861 
863 {
864  DASHContext *c = s->priv_data;
865  int ret = 0, i;
866  char *ptr;
867  char basename[1024];
868 
869  if (c->single_file_name)
870  c->single_file = 1;
871  if (c->single_file)
872  c->use_template = 0;
873 
874  av_strlcpy(c->dirname, s->url, sizeof(c->dirname));
875  ptr = strrchr(c->dirname, '/');
876  if (ptr) {
877  av_strlcpy(basename, &ptr[1], sizeof(basename));
878  ptr[1] = '\0';
879  } else {
880  c->dirname[0] = '\0';
881  av_strlcpy(basename, s->url, sizeof(basename));
882  }
883 
884  ptr = strrchr(basename, '.');
885  if (ptr)
886  *ptr = '\0';
887 
888  c->streams = av_mallocz(sizeof(*c->streams) * s->nb_streams);
889  if (!c->streams)
890  return AVERROR(ENOMEM);
891 
892  if ((ret = parse_adaptation_sets(s)) < 0)
893  return ret;
894 
895  for (i = 0; i < s->nb_streams; i++) {
896  OutputStream *os = &c->streams[i];
897  AdaptationSet *as = &c->as[os->as_idx - 1];
899  AVStream *st;
901  char filename[1024];
902 
903  os->bit_rate = s->streams[i]->codecpar->bit_rate;
904  if (os->bit_rate) {
905  snprintf(os->bandwidth_str, sizeof(os->bandwidth_str),
906  " bandwidth=\"%d\"", os->bit_rate);
907  } else {
910  av_log(s, level, "No bit rate set for stream %d\n", i);
912  return AVERROR(EINVAL);
913  }
914 
915  // copy AdaptationSet language and role from stream metadata
916  dict_copy_entry(&as->metadata, s->streams[i]->metadata, "language");
917  dict_copy_entry(&as->metadata, s->streams[i]->metadata, "role");
918 
919  ctx = avformat_alloc_context();
920  if (!ctx)
921  return AVERROR(ENOMEM);
922 
923  // choose muxer based on codec: webm for VP8/9 and opus, mp4 otherwise
924  // note: os->format_name is also used as part of the mimetype of the
925  // representation, e.g. video/<format_name>
926  if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_VP8 ||
930  snprintf(os->format_name, sizeof(os->format_name), "webm");
931  } else {
932  snprintf(os->format_name, sizeof(os->format_name), "mp4");
933  }
935  if (!ctx->oformat)
937  os->ctx = ctx;
939  ctx->opaque = s->opaque;
940  ctx->io_close = s->io_close;
941  ctx->io_open = s->io_open;
942 
943  if (!(st = avformat_new_stream(ctx, NULL)))
944  return AVERROR(ENOMEM);
947  st->time_base = s->streams[i]->time_base;
950  ctx->flags = s->flags;
951 
952  if ((ret = avio_open_dyn_buf(&ctx->pb)) < 0)
953  return ret;
954 
955  if (c->single_file) {
956  if (c->single_file_name)
957  ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), c->single_file_name, i, 0, os->bit_rate, 0);
958  else
959  snprintf(os->initfile, sizeof(os->initfile), "%s-stream%d.m4s", basename, i);
960  } else {
961  ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), c->init_seg_name, i, 0, os->bit_rate, 0);
962  }
963  snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile);
964  set_http_options(&opts, c);
965  ret = s->io_open(s, &os->out, filename, AVIO_FLAG_WRITE, &opts);
966  if (ret < 0)
967  return ret;
968  av_dict_free(&opts);
969  os->init_start_pos = 0;
970 
971  if (!strcmp(os->format_name, "mp4")) {
972  if (c->streaming)
973  av_dict_set(&opts, "movflags", "frag_every_frame+dash+delay_moov", 0);
974  else
975  av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0);
976  } else {
977  av_dict_set_int(&opts, "cluster_time_limit", c->min_seg_duration / 1000, 0);
978  av_dict_set_int(&opts, "cluster_size_limit", 5 * 1024 * 1024, 0); // set a large cluster size limit
979  av_dict_set_int(&opts, "dash", 1, 0);
980  av_dict_set_int(&opts, "dash_track_number", i + 1, 0);
981  av_dict_set_int(&opts, "live", 1, 0);
982  }
983  if ((ret = avformat_init_output(ctx, &opts)) < 0)
984  return ret;
985  os->ctx_inited = 1;
986  avio_flush(ctx->pb);
987  av_dict_free(&opts);
988 
989  av_log(s, AV_LOG_VERBOSE, "Representation %d init segment will be written to: %s\n", i, filename);
990 
991  s->streams[i]->time_base = st->time_base;
992  // If the muxer wants to shift timestamps, request to have them shifted
993  // already before being handed to this muxer, so we don't have mismatches
994  // between the MPD and the actual segments.
996  if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
997  AVRational avg_frame_rate = s->streams[i]->avg_frame_rate;
998  if (avg_frame_rate.num > 0) {
999  if (av_cmp_q(avg_frame_rate, as->min_frame_rate) < 0)
1000  as->min_frame_rate = avg_frame_rate;
1001  if (av_cmp_q(as->max_frame_rate, avg_frame_rate) < 0)
1002  as->max_frame_rate = avg_frame_rate;
1003  } else {
1004  as->ambiguous_frame_rate = 1;
1005  }
1006  c->has_video = 1;
1007  }
1008 
1009  set_codec_str(s, st->codecpar, os->codec_str, sizeof(os->codec_str));
1010  os->first_pts = AV_NOPTS_VALUE;
1011  os->max_pts = AV_NOPTS_VALUE;
1012  os->last_dts = AV_NOPTS_VALUE;
1013  os->segment_index = 1;
1014  }
1015 
1016  if (!c->has_video && c->min_seg_duration <= 0) {
1017  av_log(s, AV_LOG_WARNING, "no video stream and no min seg duration set\n");
1018  return AVERROR(EINVAL);
1019  }
1020  return 0;
1021 }
1022 
1024 {
1025  DASHContext *c = s->priv_data;
1026  int i, ret;
1027  for (i = 0; i < s->nb_streams; i++) {
1028  OutputStream *os = &c->streams[i];
1029  if ((ret = avformat_write_header(os->ctx, NULL)) < 0)
1030  return ret;
1031  // Flush init segment
1032  // Only for WebM segment, since for mp4 delay_moov is set and
1033  // the init segment is thus flushed after the first packets.
1034  if (strcmp(os->format_name, "mp4") &&
1035  (ret = flush_init_segment(s, os)) < 0)
1036  return ret;
1037  }
1038  ret = write_manifest(s, 0);
1039  if (!ret)
1040  av_log(s, AV_LOG_VERBOSE, "Manifest written to: %s\n", s->url);
1041  return ret;
1042 }
1043 
1044 static int add_segment(OutputStream *os, const char *file,
1045  int64_t time, int duration,
1046  int64_t start_pos, int64_t range_length,
1047  int64_t index_length)
1048 {
1049  int err;
1050  Segment *seg;
1051  if (os->nb_segments >= os->segments_size) {
1052  os->segments_size = (os->segments_size + 1) * 2;
1053  if ((err = av_reallocp(&os->segments, sizeof(*os->segments) *
1054  os->segments_size)) < 0) {
1055  os->segments_size = 0;
1056  os->nb_segments = 0;
1057  return err;
1058  }
1059  }
1060  seg = av_mallocz(sizeof(*seg));
1061  if (!seg)
1062  return AVERROR(ENOMEM);
1063  av_strlcpy(seg->file, file, sizeof(seg->file));
1064  seg->time = time;
1065  seg->duration = duration;
1066  if (seg->time < 0) { // If pts<0, it is expected to be cut away with an edit list
1067  seg->duration += seg->time;
1068  seg->time = 0;
1069  }
1070  seg->start_pos = start_pos;
1071  seg->range_length = range_length;
1072  seg->index_length = index_length;
1073  os->segments[os->nb_segments++] = seg;
1074  os->segment_index++;
1075  return 0;
1076 }
1077 
1078 static void write_styp(AVIOContext *pb)
1079 {
1080  avio_wb32(pb, 24);
1081  ffio_wfourcc(pb, "styp");
1082  ffio_wfourcc(pb, "msdh");
1083  avio_wb32(pb, 0); /* minor */
1084  ffio_wfourcc(pb, "msdh");
1085  ffio_wfourcc(pb, "msix");
1086 }
1087 
1088 static void find_index_range(AVFormatContext *s, const char *full_path,
1089  int64_t pos, int *index_length)
1090 {
1091  uint8_t buf[8];
1092  AVIOContext *pb;
1093  int ret;
1094 
1095  ret = s->io_open(s, &pb, full_path, AVIO_FLAG_READ, NULL);
1096  if (ret < 0)
1097  return;
1098  if (avio_seek(pb, pos, SEEK_SET) != pos) {
1099  ff_format_io_close(s, &pb);
1100  return;
1101  }
1102  ret = avio_read(pb, buf, 8);
1103  ff_format_io_close(s, &pb);
1104  if (ret < 8)
1105  return;
1106  if (AV_RL32(&buf[4]) != MKTAG('s', 'i', 'd', 'x'))
1107  return;
1108  *index_length = AV_RB32(&buf[0]);
1109 }
1110 
1112  AVCodecParameters *par)
1113 {
1114  uint8_t *extradata;
1115 
1116  if (os->ctx->streams[0]->codecpar->extradata_size || !par->extradata_size)
1117  return 0;
1118 
1119  extradata = av_malloc(par->extradata_size);
1120 
1121  if (!extradata)
1122  return AVERROR(ENOMEM);
1123 
1124  memcpy(extradata, par->extradata, par->extradata_size);
1125 
1126  os->ctx->streams[0]->codecpar->extradata = extradata;
1128 
1129  set_codec_str(s, par, os->codec_str, sizeof(os->codec_str));
1130 
1131  return 0;
1132 }
1133 
1134 static void dashenc_delete_file(AVFormatContext *s, char *filename) {
1135  DASHContext *c = s->priv_data;
1136  int http_base_proto = ff_is_http_proto(filename);
1137 
1138  if (http_base_proto) {
1139  AVIOContext *out = NULL;
1140  AVDictionary *http_opts = NULL;
1141 
1142  set_http_options(&http_opts, c);
1143  av_dict_set(&http_opts, "method", "DELETE", 0);
1144 
1145  if (dashenc_io_open(s, &out, filename, &http_opts) < 0) {
1146  av_log(s, AV_LOG_ERROR, "failed to delete %s\n", filename);
1147  }
1148 
1149  av_dict_free(&http_opts);
1150  dashenc_io_close(s, &out, filename);
1151  } else if (unlink(filename) < 0) {
1152  av_log(s, AV_LOG_ERROR, "failed to delete %s: %s\n", filename, strerror(errno));
1153  }
1154 }
1155 
1156 static int dash_flush(AVFormatContext *s, int final, int stream)
1157 {
1158  DASHContext *c = s->priv_data;
1159  int i, ret = 0;
1160 
1161  const char *proto = avio_find_protocol_name(s->url);
1162  int use_rename = proto && !strcmp(proto, "file");
1163 
1164  int cur_flush_segment_index = 0;
1165  if (stream >= 0)
1166  cur_flush_segment_index = c->streams[stream].segment_index;
1167 
1168  for (i = 0; i < s->nb_streams; i++) {
1169  OutputStream *os = &c->streams[i];
1170  AVStream *st = s->streams[i];
1171  int range_length, index_length = 0;
1172 
1173  if (!os->packets_written)
1174  continue;
1175 
1176  // Flush the single stream that got a keyframe right now.
1177  // Flush all audio streams as well, in sync with video keyframes,
1178  // but not the other video streams.
1179  if (stream >= 0 && i != stream) {
1181  continue;
1182  // Make sure we don't flush audio streams multiple times, when
1183  // all video streams are flushed one at a time.
1184  if (c->has_video && os->segment_index > cur_flush_segment_index)
1185  continue;
1186  }
1187 
1188  if (!c->single_file) {
1189  if (!strcmp(os->format_name, "mp4") && !os->written_len)
1190  write_styp(os->ctx->pb);
1191  } else {
1192  snprintf(os->full_path, sizeof(os->full_path), "%s%s", c->dirname, os->initfile);
1193  }
1194 
1195  ret = flush_dynbuf(os, &range_length);
1196  if (ret < 0)
1197  break;
1198  os->packets_written = 0;
1199 
1200  if (c->single_file) {
1201  find_index_range(s, os->full_path, os->pos, &index_length);
1202  } else {
1203  dashenc_io_close(s, &os->out, os->temp_path);
1204 
1205  if (use_rename) {
1206  ret = avpriv_io_move(os->temp_path, os->full_path);
1207  if (ret < 0)
1208  break;
1209  }
1210  }
1211 
1212  if (!os->bit_rate) {
1213  // calculate average bitrate of first segment
1214  int64_t bitrate = (int64_t) range_length * 8 * AV_TIME_BASE / av_rescale_q(os->max_pts - os->start_pts,
1215  st->time_base,
1216  AV_TIME_BASE_Q);
1217  if (bitrate >= 0) {
1218  os->bit_rate = bitrate;
1219  snprintf(os->bandwidth_str, sizeof(os->bandwidth_str),
1220  " bandwidth=\"%d\"", os->bit_rate);
1221  }
1222  }
1223  add_segment(os, os->filename, os->start_pts, os->max_pts - os->start_pts, os->pos, range_length, index_length);
1224  av_log(s, AV_LOG_VERBOSE, "Representation %d media segment %d written to: %s\n", i, os->segment_index, os->full_path);
1225 
1226  os->pos += range_length;
1227  }
1228 
1229  if (c->window_size || (final && c->remove_at_exit)) {
1230  for (i = 0; i < s->nb_streams; i++) {
1231  OutputStream *os = &c->streams[i];
1232  int j;
1233  int remove = os->nb_segments - c->window_size - c->extra_window_size;
1234  if (final && c->remove_at_exit)
1235  remove = os->nb_segments;
1236  if (remove > 0) {
1237  for (j = 0; j < remove; j++) {
1238  char filename[1024];
1239  snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->segments[j]->file);
1240  dashenc_delete_file(s, filename);
1241  av_free(os->segments[j]);
1242  }
1243  os->nb_segments -= remove;
1244  memmove(os->segments, os->segments + remove, os->nb_segments * sizeof(*os->segments));
1245  }
1246  }
1247  }
1248 
1249  if (ret >= 0)
1250  ret = write_manifest(s, final);
1251  return ret;
1252 }
1253 
1255 {
1256  DASHContext *c = s->priv_data;
1257  AVStream *st = s->streams[pkt->stream_index];
1258  OutputStream *os = &c->streams[pkt->stream_index];
1259  int ret;
1260 
1261  ret = update_stream_extradata(s, os, st->codecpar);
1262  if (ret < 0)
1263  return ret;
1264 
1265  // Fill in a heuristic guess of the packet duration, if none is available.
1266  // The mp4 muxer will do something similar (for the last packet in a fragment)
1267  // if nothing is set (setting it for the other packets doesn't hurt).
1268  // By setting a nonzero duration here, we can be sure that the mp4 muxer won't
1269  // invoke its heuristic (this doesn't have to be identical to that algorithm),
1270  // so that we know the exact timestamps of fragments.
1271  if (!pkt->duration && os->last_dts != AV_NOPTS_VALUE)
1272  pkt->duration = pkt->dts - os->last_dts;
1273  os->last_dts = pkt->dts;
1274 
1275  // If forcing the stream to start at 0, the mp4 muxer will set the start
1276  // timestamps to 0. Do the same here, to avoid mismatches in duration/timestamps.
1277  if (os->first_pts == AV_NOPTS_VALUE &&
1279  pkt->pts -= pkt->dts;
1280  pkt->dts = 0;
1281  }
1282 
1283  if (os->first_pts == AV_NOPTS_VALUE)
1284  os->first_pts = pkt->pts;
1285 
1286  if ((!c->has_video || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) &&
1287  pkt->flags & AV_PKT_FLAG_KEY && os->packets_written &&
1288  av_compare_ts(pkt->pts - os->start_pts, st->time_base,
1289  c->min_seg_duration, AV_TIME_BASE_Q) >= 0) {
1290  int64_t prev_duration = c->last_duration;
1291 
1292  c->last_duration = av_rescale_q(pkt->pts - os->start_pts,
1293  st->time_base,
1294  AV_TIME_BASE_Q);
1295  c->total_duration = av_rescale_q(pkt->pts - os->first_pts,
1296  st->time_base,
1297  AV_TIME_BASE_Q);
1298 
1299  if ((!c->use_timeline || !c->use_template) && prev_duration) {
1300  if (c->last_duration < prev_duration*9/10 ||
1301  c->last_duration > prev_duration*11/10) {
1303  "Segment durations differ too much, enable use_timeline "
1304  "and use_template, or keep a stricter keyframe interval\n");
1305  }
1306  }
1307 
1308  if ((ret = dash_flush(s, 0, pkt->stream_index)) < 0)
1309  return ret;
1310  }
1311 
1312  if (!os->packets_written) {
1313  // If we wrote a previous segment, adjust the start time of the segment
1314  // to the end of the previous one (which is the same as the mp4 muxer
1315  // does). This avoids gaps in the timeline.
1316  if (os->max_pts != AV_NOPTS_VALUE)
1317  os->start_pts = os->max_pts;
1318  else
1319  os->start_pts = pkt->pts;
1320  }
1321  if (os->max_pts == AV_NOPTS_VALUE)
1322  os->max_pts = pkt->pts + pkt->duration;
1323  else
1324  os->max_pts = FFMAX(os->max_pts, pkt->pts + pkt->duration);
1325  os->packets_written++;
1326  if ((ret = ff_write_chained(os->ctx, 0, pkt, s, 0)) < 0)
1327  return ret;
1328 
1329  if (!os->init_range_length)
1330  flush_init_segment(s, os);
1331 
1332  //open the output context when the first frame of a segment is ready
1333  if (!c->single_file && os->packets_written == 1) {
1334  AVDictionary *opts = NULL;
1335  const char *proto = avio_find_protocol_name(s->url);
1336  int use_rename = proto && !strcmp(proto, "file");
1337  os->filename[0] = os->full_path[0] = os->temp_path[0] = '\0';
1338  ff_dash_fill_tmpl_params(os->filename, sizeof(os->filename),
1339  c->media_seg_name, pkt->stream_index,
1340  os->segment_index, os->bit_rate, os->start_pts);
1341  snprintf(os->full_path, sizeof(os->full_path), "%s%s", c->dirname,
1342  os->filename);
1343  snprintf(os->temp_path, sizeof(os->temp_path),
1344  use_rename ? "%s.tmp" : "%s", os->full_path);
1345  set_http_options(&opts, c);
1346  ret = dashenc_io_open(s, &os->out, os->temp_path, &opts);
1347  if (ret < 0)
1348  return ret;
1349  av_dict_free(&opts);
1350  }
1351 
1352  //write out the data immediately in streaming mode
1353  if (c->streaming && !strcmp(os->format_name, "mp4")) {
1354  int len = 0;
1355  uint8_t *buf = NULL;
1356  if (!os->written_len)
1357  write_styp(os->ctx->pb);
1358  avio_flush(os->ctx->pb);
1359  len = avio_get_dyn_buf (os->ctx->pb, &buf);
1360  avio_write(os->out, buf + os->written_len, len - os->written_len);
1361  os->written_len = len;
1362  avio_flush(os->out);
1363  }
1364 
1365  return ret;
1366 }
1367 
1369 {
1370  DASHContext *c = s->priv_data;
1371 
1372  if (s->nb_streams > 0) {
1373  OutputStream *os = &c->streams[0];
1374  // If no segments have been written so far, try to do a crude
1375  // guess of the segment duration
1376  if (!c->last_duration)
1378  s->streams[0]->time_base,
1379  AV_TIME_BASE_Q);
1381  s->streams[0]->time_base,
1382  AV_TIME_BASE_Q);
1383  }
1384  dash_flush(s, 1, -1);
1385 
1386  if (c->remove_at_exit) {
1387  char filename[1024];
1388  int i;
1389  for (i = 0; i < s->nb_streams; i++) {
1390  OutputStream *os = &c->streams[i];
1391  snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile);
1392  dashenc_delete_file(s, filename);
1393  }
1394  dashenc_delete_file(s, s->url);
1395  }
1396 
1397  return 0;
1398 }
1399 
1400 static int dash_check_bitstream(struct AVFormatContext *s, const AVPacket *avpkt)
1401 {
1402  DASHContext *c = s->priv_data;
1403  OutputStream *os = &c->streams[avpkt->stream_index];
1404  AVFormatContext *oc = os->ctx;
1405  if (oc->oformat->check_bitstream) {
1406  int ret;
1407  AVPacket pkt = *avpkt;
1408  pkt.stream_index = 0;
1409  ret = oc->oformat->check_bitstream(oc, &pkt);
1410  if (ret == 1) {
1411  AVStream *st = s->streams[avpkt->stream_index];
1412  AVStream *ost = oc->streams[0];
1413  st->internal->bsfcs = ost->internal->bsfcs;
1414  st->internal->nb_bsfcs = ost->internal->nb_bsfcs;
1415  ost->internal->bsfcs = NULL;
1416  ost->internal->nb_bsfcs = 0;
1417  }
1418  return ret;
1419  }
1420  return 1;
1421 }
1422 
1423 #define OFFSET(x) offsetof(DASHContext, x)
1424 #define E AV_OPT_FLAG_ENCODING_PARAM
1425 static const AVOption options[] = {
1426  { "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 },
1427  { "window_size", "number of segments kept in the manifest", OFFSET(window_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, E },
1428  { "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 },
1429  { "min_seg_duration", "minimum segment duration (in microseconds)", OFFSET(min_seg_duration), AV_OPT_TYPE_INT, { .i64 = 5000000 }, 0, INT_MAX, E },
1430  { "remove_at_exit", "remove all segments when finished", OFFSET(remove_at_exit), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1431  { "use_template", "Use SegmentTemplate instead of SegmentList", OFFSET(use_template), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },
1432  { "use_timeline", "Use SegmentTimeline in SegmentTemplate", OFFSET(use_timeline), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },
1433  { "single_file", "Store all segments in one file, accessed using byte ranges", OFFSET(single_file), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1434  { "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 },
1435  { "init_seg_name", "DASH-templated name to used for the initialization segment", OFFSET(init_seg_name), AV_OPT_TYPE_STRING, {.str = "init-stream$RepresentationID$.m4s"}, 0, 0, E },
1436  { "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$.m4s"}, 0, 0, E },
1437  { "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 },
1438  { "method", "set the HTTP method", OFFSET(method), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
1439  { "http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
1440  { "http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
1441  { "hls_playlist", "Generate HLS playlist files(master.m3u8, media_%d.m3u8)", OFFSET(hls_playlist), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1442  { "streaming", "Enable/Disable streaming mode of output. Each frame will be moof fragment", OFFSET(streaming), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1443  { "timeout", "set timeout for socket I/O operations", OFFSET(timeout), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT_MAX, .flags = E },
1444  { NULL },
1445 };
1446 
1447 static const AVClass dash_class = {
1448  .class_name = "dash muxer",
1449  .item_name = av_default_item_name,
1450  .option = options,
1451  .version = LIBAVUTIL_VERSION_INT,
1452 };
1453 
1455  .name = "dash",
1456  .long_name = NULL_IF_CONFIG_SMALL("DASH Muxer"),
1457  .extensions = "mpd",
1458  .priv_data_size = sizeof(DASHContext),
1459  .audio_codec = AV_CODEC_ID_AAC,
1460  .video_codec = AV_CODEC_ID_H264,
1462  .init = dash_init,
1466  .deinit = dash_free,
1467  .check_bitstream = dash_check_bitstream,
1468  .priv_class = &dash_class,
1469 };
static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int unqueue)
Definition: ffmpeg.c:679
#define NULL
Definition: coverity.c:32
const char * s
Definition: avisynth_c.h:768
Bytestream IO Context.
Definition: avio.h:161
int use_timeline
Definition: dashenc.c:100
static int dict_copy_entry(AVDictionary **dst, const AVDictionary *src, const char *key)
Definition: dashenc.c:854
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition: avformat.h:1618
static void set_http_options(AVDictionary **options, DASHContext *c)
Definition: dashenc.c:265
int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition: aviobuf.c:1420
AVOption.
Definition: opt.h:246
static int parse_adaptation_sets(AVFormatContext *s)
Definition: dashenc.c:602
void * av_realloc(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory.
Definition: mem.c:135
int min_seg_duration
Definition: dashenc.c:97
static const AVOption options[]
Definition: dashenc.c:1425
AVIOContext * mpd_out
Definition: dashenc.c:117
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file.
Definition: mux.c:878
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
int ambiguous_frame_rate
Definition: dashenc.c:64
#define AV_DICT_DONT_OVERWRITE
Don't overwrite existing entries.
Definition: dict.h:79
int range_length
Definition: dashenc.c:53
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
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:1311
int nb_segments
Definition: dashenc.c:76
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: avcodec.h:3884
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition: avformat.h:935
int num
Numerator.
Definition: rational.h:59
static void dashenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename)
Definition: dashenc.c:151
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:246
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:191
#define AVIO_FLAG_READ
read-only
Definition: avio.h:654
int n
Definition: dashenc.c:56
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:632
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:655
char codec_str[100]
Definition: dashenc.c:83
Convenience header that includes libavutil's core.
char filename[1024]
Definition: dashenc.c:85
int64_t timeout
Definition: dashenc.c:120
const char * key
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)
Definition: hlsplaylist.c:103
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
AVFormatContext * ctx
Definition: dashenc.c:68
int single_file
Definition: dashenc.c:101
static AVPacket pkt
int ff_is_http_proto(char *filename)
Utility function to check if the file uses http or https protocol.
Definition: utils.c:5615
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:87
#define src
Definition: vp8dsp.c:254
int packets_written
Definition: dashenc.c:72
int as_idx
Definition: dashenc.c:69
int64_t start_pts
Definition: dashenc.c:78
int avio_open_dyn_buf(AVIOContext **s)
Open a write only memory stream.
Definition: aviobuf.c:1391
int strict_std_compliance
Allow non-standard and experimental extension.
Definition: avformat.h:1648
static int dash_init(AVFormatContext *s)
Definition: dashenc.c:862
This struct describes the properties of an encoded stream.
Definition: avcodec.h:3876
int ffurl_shutdown(URLContext *h, int flags)
Signal the URLContext that we are done reading or writing the stream.
Definition: avio.c:657
int avpriv_io_move(const char *url_src, const char *url_dst)
Move or rename a resource.
Definition: avio.c:499
static struct codec_string codecs[]
int64_t last_dts
Definition: dashenc.c:79
Format I/O context.
Definition: avformat.h:1342
int64_t init_start_pos
Definition: dashenc.c:74
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
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
static int64_t start_time
Definition: ffplay.c:327
int streaming
Definition: dashenc.c:119
char * adaptation_sets
Definition: dashenc.c:92
int mem
Definition: avisynth_c.h:821
AdaptationSet * as
Definition: dashenc.c:93
uint8_t
#define av_malloc(s)
int width
Video only.
Definition: avcodec.h:3950
AVRational min_frame_rate
Definition: dashenc.c:63
AVOptions.
miscellaneous OS support macros and functions.
const AVCodecTag ff_codec_movvideo_tags[]
Definition: isom.c:75
static int add_adaptation_set(AVFormatContext *s, AdaptationSet **as, enum AVMediaType type)
Definition: dashenc.c:567
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: avcodec.h:1448
void ff_format_io_close(AVFormatContext *s, AVIOContext **pb)
Definition: utils.c:5608
int extra_window_size
Definition: dashenc.c:96
int ctx_inited
Definition: dashenc.c:69
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4450
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:87
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1410
int64_t duration
Definition: movenc.c:63
const char * method
Definition: dashenc.c:112
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
Definition: options.c:144
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
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1473
static int flags
Definition: log.c:55
uint32_t tag
Definition: movenc.c:1455
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
AVIOContext * m3u8_out
Definition: dashenc.c:118
void ff_hls_write_audio_rendition(AVIOContext *out, char *agroup, char *filename, int name_id, int is_default)
Definition: hlsplaylist.c:38
ptrdiff_t size
Definition: opengl_enc.c:101
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:218
static av_always_inline void ffio_wfourcc(AVIOContext *pb, const uint8_t *s)
Definition: avio_internal.h:58
uint64_t availability_start_time
Definition: dashdec.c:134
char initfile[1024]
Definition: dashenc.c:73
static void format_date_now(char *buf, int size)
Definition: dashenc.c:508
char format_name[8]
Definition: dashenc.c:71
#define av_log(a,...)
#define AV_OPT_FLAG_ENCODING_PARAM
a generic parameter which can be set by the user for muxing or encoding
Definition: opt.h:276
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:648
struct AVOutputFormat * oformat
The output container format.
Definition: avformat.h:1361
int64_t bit_rate
The average bitrate of the encoded data (in bits per second).
Definition: avcodec.h:3913
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: avcodec.h:1462
static void get_hls_playlist_name(char *playlist_name, int string_size, const char *base_url, int id)
Definition: dashenc.c:277
static void write_time(AVIOContext *out, int64_t time)
Definition: dashenc.c:492
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
static int write_manifest(AVFormatContext *s, int final)
Definition: dashenc.c:701
#define E
Definition: dashenc.c:1424
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
Copy the contents of src to dst.
Definition: utils.c:2003
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
AVDictionary * metadata
Metadata that applies to the whole file.
Definition: avformat.h:1580
int hls_playlist
Definition: dashenc.c:114
AVDictionary * metadata
Definition: dashenc.c:62
int remove_at_exit
Definition: dashenc.c:98
#define AVERROR(e)
Definition: error.h:43
int64_t last_duration
Definition: dashenc.c:104
static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
Definition: dashenc.c:1254
int nb_as
Definition: dashenc.c:94
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
int avio_close(AVIOContext *s)
Close the resource accessed by the AVIOContext s and free it.
Definition: aviobuf.c:1190
int duration
Definition: dashenc.c:55
char * url
input or output URL.
Definition: avformat.h:1438
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values. ...
Definition: dict.c:203
enum AVMediaType codec_type
General type of the encoded data.
Definition: avcodec.h:3880
simple assert() macros that are a bit more flexible than ISO C assert().
static int dash_check_bitstream(struct AVFormatContext *s, const AVPacket *avpkt)
Definition: dashenc.c:1400
static int flush_init_segment(AVFormatContext *s, OutputStream *os)
Definition: dashenc.c:285
int64_t start_pos
Definition: dashenc.c:52
AVRational avg_frame_rate
Average framerate.
Definition: avformat.h:946
#define FFMAX(a, b)
Definition: common.h:94
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
char bandwidth_str[64]
Definition: dashenc.c:81
const AVCodecTag ff_mp4_obj_type[]
Definition: isom.c:34
static void dashenc_delete_file(AVFormatContext *s, char *filename)
Definition: dashenc.c:1134
static struct tm * gmtime_r(const time_t *clock, struct tm *result)
Definition: time_internal.h:26
int flags
A combination of AV_PKT_FLAG values.
Definition: avcodec.h:1436
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
int extradata_size
Size of the extradata content in bytes.
Definition: avcodec.h:3902
void * opaque
User data.
Definition: avformat.h:1846
AVOutputFormat ff_dash_muxer
Definition: dashenc.c:1454
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition: avformat.h:1398
void ff_hls_write_playlist_header(AVIOContext *out, int version, int allowcache, int target_duration, int64_t sequence, uint32_t playlist_type)
Definition: hlsplaylist.c:74
AVDictionary * opts
Definition: movenc.c:50
AVBSFContext ** bsfcs
bitstream filters to run on stream
Definition: internal.h:161
const char * media_seg_name
Definition: dashenc.c:110
char * user_agent
holds HTTP user agent set as an AVOption to the HTTP protocol context
Definition: dashdec.c:146
int void avio_flush(AVIOContext *s)
Force flushing of buffered data.
Definition: aviobuf.c:238
#define AV_TIME_BASE
Internal time base represented as integer.
Definition: avutil.h:254
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
int segment_index
Definition: dashenc.c:76
static int write_trailer(AVFormatContext *s1)
Definition: v4l2enc.c:94
#define AVFMT_GLOBALHEADER
Format wants global header.
Definition: avformat.h:468
const char * name
Definition: avformat.h:507
int master_playlist_created
Definition: dashenc.c:116
AVFormatContext * ctx
Definition: movenc.c:48
char full_path[1024]
Definition: dashenc.c:86
char dirname[1024]
Definition: dashenc.c:107
enum AVMediaType media_type
Definition: dashenc.c:61
int avoid_negative_ts
Avoid negative timestamps during muxing.
Definition: avformat.h:1671
int n
Definition: avisynth_c.h:684
AVDictionary * metadata
Definition: avformat.h:937
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
Usually treated as AVMEDIA_TYPE_DATA.
Definition: avutil.h:200
static struct @271 state
int64_t pos
Definition: dashenc.c:74
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
int segments_size
Definition: dashenc.c:76
#define OFFSET(x)
Definition: dashenc.c:1423
void ffio_free_dyn_buf(AVIOContext **s)
Free a dynamic buffer.
Definition: aviobuf.c:1450
Stream structure.
Definition: avformat.h:873
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
int64_t time
Definition: dashenc.c:54
Segment ** segments
Definition: dashenc.c:77
void ff_hls_write_playlist_version(AVIOContext *out, int version)
Definition: hlsplaylist.c:31
int index_length
Definition: dashenc.c:53
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
AVStreamInternal * internal
An opaque field for libavformat internal usage.
Definition: avformat.h:1223
const AVCodecTag ff_codec_movaudio_tags[]
Definition: isom.c:312
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:260
AVIOContext * pb
I/O context.
Definition: avformat.h:1384
int bit_rate
Definition: dashenc.c:80
int use_template
Definition: dashenc.c:99
int written_len
Definition: dashenc.c:84
AVRational max_frame_rate
Definition: dashenc.c:63
void * buf
Definition: avisynth_c.h:690
Definition: url.h:38
GLint GLenum type
Definition: opengl_enc.c:105
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
static void set_codec_str(AVFormatContext *s, AVCodecParameters *par, char *str, int size)
Definition: dashenc.c:167
Describe the class of an AVClass context structure.
Definition: log.h:67
const char * init_seg_name
Definition: dashenc.c:109
Rational number (pair of numerator and denominator).
Definition: rational.h:58
static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_index, int final)
Definition: dashenc.c:519
AVMediaType
Definition: avutil.h:199
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition: avstring.c:101
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:1178
#define FF_COMPLIANCE_STRICT
Strictly conform to all the things in the spec no matter what consequences.
Definition: avcodec.h:2578
#define snprintf
Definition: snprintf.h:34
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition: utils.c:4384
static int adaptation_set_add_stream(AVFormatContext *s, int as_idx, int i)
Definition: dashenc.c:584
int64_t total_duration
Definition: dashenc.c:105
static void find_index_range(AVFormatContext *s, const char *full_path, int64_t pos, int *index_length)
Definition: dashenc.c:1088
char file[1024]
Definition: dashenc.c:51
const char * avio_find_protocol_name(const char *url)
Return the name of the protocol that will handle the passed URL.
Definition: avio.c:473
static int dashenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename, AVDictionary **options)
Definition: dashenc.c:134
URLContext * ffio_geturlcontext(AVIOContext *s)
Return the URLContext associated with the AVIOContext.
Definition: aviobuf.c:1039
static int flush_dynbuf(OutputStream *os, int *range_length)
Definition: dashenc.c:242
uint8_t level
Definition: svq3.c:207
OutputStream * streams
Definition: dashenc.c:102
void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, int bandwidth, char *filename, char *agroup, char *codecs, char *ccgroup)
Definition: hlsplaylist.c:48
int init_range_length
Definition: dashenc.c:75
int ff_http_do_new_request(URLContext *h, const char *uri)
Send a new HTTP request, reusing the old connection.
Definition: http.c:307
int sample_rate
Audio only.
Definition: avcodec.h:3994
#define AVFMT_AVOID_NEG_TS_MAKE_ZERO
Shift timestamps so that they start at 0.
Definition: avformat.h:1674
static int av_cmp_q(AVRational a, AVRational b)
Compare two rationals.
Definition: rational.h:89
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
static AVStream * ost
Main libavformat public API header.
if(ret< 0)
Definition: vf_mcdeint.c:279
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:465
Utilties for rational number calculation.
const char * user_agent
Definition: dashenc.c:113
const char * single_file_name
Definition: dashenc.c:108
static double c[64]
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
void ff_hls_write_init_file(AVIOContext *out, char *filename, int byterange_mode, int64_t size, int64_t pos)
Definition: hlsplaylist.c:94
int den
Denominator.
Definition: rational.h:60
static void write_styp(AVIOContext *pb)
Definition: dashenc.c:1078
static int dash_write_header(AVFormatContext *s)
Definition: dashenc.c:1023
char id[10]
Definition: dashenc.c:60
#define av_free(p)
char * value
Definition: dict.h:87
int len
const char * str
Definition: dashenc.c:125
void * priv_data
Format private data.
Definition: avformat.h:1370
const char * utc_timing_url
Definition: dashenc.c:111
static int dash_write_trailer(AVFormatContext *s)
Definition: dashenc.c:1368
int window_size
Definition: dashenc.c:95
static void write_header(FFV1Context *f)
Definition: ffv1enc.c:337
#define lrint
Definition: tablegen.h:53
static void dash_free(AVFormatContext *s)
Definition: dashenc.c:300
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: avcodec.h:3898
int has_video
Definition: dashenc.c:103
int channels
Audio only.
Definition: avcodec.h:3990
int64_t max_pts
Definition: dashenc.c:78
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed...
Definition: avcodec.h:1429
void ff_hls_write_end_list(AVIOContext *out)
Definition: hlsplaylist.c:156
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
Definition: mux.c:1247
void avio_wb32(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:377
static void output_segment_list(OutputStream *os, AVIOContext *out, AVFormatContext *s, int representation_id, int final)
Definition: dashenc.c:333
FILE * out
Definition: movenc.c:54
#define av_freep(p)
static int update_stream_extradata(AVFormatContext *s, OutputStream *os, AVCodecParameters *par)
Definition: dashenc.c:1111
unbuffered private I/O API
#define AVERROR_MUXER_NOT_FOUND
Muxer not found.
Definition: error.h:60
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1020
static char * xmlescape(const char *str)
Definition: dashenc.c:452
AVIOContext * out
Definition: dashenc.c:70
char temp_path[1024]
Definition: dashenc.c:87
static int dash_flush(AVFormatContext *s, int final, int stream)
Definition: dashenc.c:1156
int stream_index
Definition: avcodec.h:1432
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avformat.h:902
int64_t first_pts
Definition: ffmpeg.h:455
#define MKTAG(a, b, c, d)
Definition: common.h:366
unsigned int av_codec_get_tag(const struct AVCodecTag *const *tags, enum AVCodecID id)
Get the codec tag for the given codec id id.
#define AVFMT_TS_NEGATIVE
Format allows muxing negative timestamps.
Definition: avformat.h:484
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:1922
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Definition: bytestream.h:87
This structure stores compressed data.
Definition: avcodec.h:1407
void(* io_close)(struct AVFormatContext *s, AVIOContext *pb)
A callback for closing the streams opened with AVFormatContext.io_open().
Definition: avformat.h:1928
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:1423
int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len)
Definition: avc.c:107
static const AVClass dash_class
Definition: dashenc.c:1447
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
GLuint buffer
Definition: opengl_enc.c:102
int avio_printf(AVIOContext *s, const char *fmt,...) av_printf_format(2
#define AV_WL32(p, v)
Definition: intreadwrite.h:426
int http_persistent
Definition: dashenc.c:115
static int add_segment(OutputStream *os, const char *file, int64_t time, int duration, int64_t start_pos, int64_t range_length, int64_t index_length)
Definition: dashenc.c:1044
int avio_get_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition: aviobuf.c:1403
static uint8_t tmp[11]
Definition: aes_ctr.c:26