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  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include "config.h"
23 #if HAVE_UNISTD_H
24 #include <unistd.h>
25 #endif
26 
27 #include "libavutil/avassert.h"
28 #include "libavutil/avutil.h"
29 #include "libavutil/avstring.h"
30 #include "libavutil/intreadwrite.h"
31 #include "libavutil/mathematics.h"
32 #include "libavutil/opt.h"
33 #include "libavutil/rational.h"
35 
36 #include "avc.h"
37 #include "avformat.h"
38 #include "avio_internal.h"
39 #include "internal.h"
40 #include "isom.h"
41 #include "os_support.h"
42 #include "url.h"
43 #include "dash.h"
44 
45 typedef struct Segment {
46  char file[1024];
47  int64_t start_pos;
49  int64_t time;
50  int duration;
51  int n;
52 } Segment;
53 
54 typedef struct AdaptationSet {
55  char id[10];
59 
60 typedef struct OutputStream {
64  char format_name[8];
66  char initfile[1024];
67  int64_t init_start_pos, pos;
72  int64_t last_dts;
73  int bit_rate;
74  char bandwidth_str[64];
75 
76  char codec_str[100];
77 } OutputStream;
78 
79 typedef struct DASHContext {
80  const AVClass *class; /* Class for private options. */
83  int nb_as;
92  int has_video;
93  int64_t last_duration;
94  int64_t total_duration;
96  char dirname[1024];
97  const char *single_file_name;
98  const char *init_seg_name;
99  const char *media_seg_name;
102  const char *utc_timing_url;
103 } DASHContext;
104 
105 static struct codec_string {
106  int id;
107  const char *str;
108 } codecs[] = {
109  { AV_CODEC_ID_VP8, "vp8" },
110  { AV_CODEC_ID_VP9, "vp9" },
111  { AV_CODEC_ID_VORBIS, "vorbis" },
112  { AV_CODEC_ID_OPUS, "opus" },
113  { 0, NULL }
114 };
115 
117  char *str, int size)
118 {
119  const AVCodecTag *tags[2] = { NULL, NULL };
120  uint32_t tag;
121  int i;
122 
123  // common Webm codecs are not part of RFC 6381
124  for (i = 0; codecs[i].id; i++)
125  if (codecs[i].id == par->codec_id) {
126  av_strlcpy(str, codecs[i].str, size);
127  return;
128  }
129 
130  // for codecs part of RFC 6381
131  if (par->codec_type == AVMEDIA_TYPE_VIDEO)
132  tags[0] = ff_codec_movvideo_tags;
133  else if (par->codec_type == AVMEDIA_TYPE_AUDIO)
134  tags[0] = ff_codec_movaudio_tags;
135  else
136  return;
137 
138  tag = av_codec_get_tag(tags, par->codec_id);
139  if (!tag)
140  return;
141  if (size < 5)
142  return;
143 
144  AV_WL32(str, tag);
145  str[4] = '\0';
146  if (!strcmp(str, "mp4a") || !strcmp(str, "mp4v")) {
147  uint32_t oti;
148  tags[0] = ff_mp4_obj_type;
149  oti = av_codec_get_tag(tags, par->codec_id);
150  if (oti)
151  av_strlcatf(str, size, ".%02"PRIx32, oti);
152  else
153  return;
154 
155  if (tag == MKTAG('m', 'p', '4', 'a')) {
156  if (par->extradata_size >= 2) {
157  int aot = par->extradata[0] >> 3;
158  if (aot == 31)
159  aot = ((AV_RB16(par->extradata) >> 5) & 0x3f) + 32;
160  av_strlcatf(str, size, ".%d", aot);
161  }
162  } else if (tag == MKTAG('m', 'p', '4', 'v')) {
163  // Unimplemented, should output ProfileLevelIndication as a decimal number
164  av_log(s, AV_LOG_WARNING, "Incomplete RFC 6381 codec string for mp4v\n");
165  }
166  } else if (!strcmp(str, "avc1")) {
167  uint8_t *tmpbuf = NULL;
168  uint8_t *extradata = par->extradata;
169  int extradata_size = par->extradata_size;
170  if (!extradata_size)
171  return;
172  if (extradata[0] != 1) {
173  AVIOContext *pb;
174  if (avio_open_dyn_buf(&pb) < 0)
175  return;
176  if (ff_isom_write_avcc(pb, extradata, extradata_size) < 0) {
177  ffio_free_dyn_buf(&pb);
178  return;
179  }
180  extradata_size = avio_close_dyn_buf(pb, &extradata);
181  tmpbuf = extradata;
182  }
183 
184  if (extradata_size >= 4)
185  av_strlcatf(str, size, ".%02x%02x%02x",
186  extradata[1], extradata[2], extradata[3]);
187  av_free(tmpbuf);
188  }
189 }
190 
191 static int flush_dynbuf(OutputStream *os, int *range_length)
192 {
193  uint8_t *buffer;
194 
195  if (!os->ctx->pb) {
196  return AVERROR(EINVAL);
197  }
198 
199  // flush
200  av_write_frame(os->ctx, NULL);
201  avio_flush(os->ctx->pb);
202 
203  // write out to file
204  *range_length = avio_close_dyn_buf(os->ctx->pb, &buffer);
205  os->ctx->pb = NULL;
206  avio_write(os->out, buffer, *range_length);
207  av_free(buffer);
208 
209  // re-open buffer
210  return avio_open_dyn_buf(&os->ctx->pb);
211 }
212 
214 {
215  DASHContext *c = s->priv_data;
216  int ret, range_length;
217 
218  ret = flush_dynbuf(os, &range_length);
219  if (ret < 0)
220  return ret;
221 
222  os->pos = os->init_range_length = range_length;
223  if (!c->single_file)
224  ff_format_io_close(s, &os->out);
225  return 0;
226 }
227 
229 {
230  DASHContext *c = s->priv_data;
231  int i, j;
232 
233  if (c->as) {
234  for (i = 0; i < c->nb_as; i++)
235  av_dict_free(&c->as[i].metadata);
236  av_freep(&c->as);
237  c->nb_as = 0;
238  }
239 
240  if (!c->streams)
241  return;
242  for (i = 0; i < s->nb_streams; i++) {
243  OutputStream *os = &c->streams[i];
244  if (os->ctx && os->ctx_inited)
245  av_write_trailer(os->ctx);
246  if (os->ctx && os->ctx->pb)
247  ffio_free_dyn_buf(&os->ctx->pb);
248  ff_format_io_close(s, &os->out);
249  if (os->ctx)
251  for (j = 0; j < os->nb_segments; j++)
252  av_free(os->segments[j]);
253  av_free(os->segments);
254  }
255  av_freep(&c->streams);
256 }
257 
259 {
260  int i, start_index = 0, start_number = 1;
261  if (c->window_size) {
262  start_index = FFMAX(os->nb_segments - c->window_size, 0);
263  start_number = FFMAX(os->segment_index - c->window_size, 1);
264  }
265 
266  if (c->use_template) {
267  int timescale = c->use_timeline ? os->ctx->streams[0]->time_base.den : AV_TIME_BASE;
268  avio_printf(out, "\t\t\t\t<SegmentTemplate timescale=\"%d\" ", timescale);
269  if (!c->use_timeline)
270  avio_printf(out, "duration=\"%"PRId64"\" ", c->last_duration);
271  avio_printf(out, "initialization=\"%s\" media=\"%s\" startNumber=\"%d\">\n", c->init_seg_name, c->media_seg_name, c->use_timeline ? start_number : 1);
272  if (c->use_timeline) {
273  int64_t cur_time = 0;
274  avio_printf(out, "\t\t\t\t\t<SegmentTimeline>\n");
275  for (i = start_index; i < os->nb_segments; ) {
276  Segment *seg = os->segments[i];
277  int repeat = 0;
278  avio_printf(out, "\t\t\t\t\t\t<S ");
279  if (i == start_index || seg->time != cur_time) {
280  cur_time = seg->time;
281  avio_printf(out, "t=\"%"PRId64"\" ", seg->time);
282  }
283  avio_printf(out, "d=\"%d\" ", seg->duration);
284  while (i + repeat + 1 < os->nb_segments &&
285  os->segments[i + repeat + 1]->duration == seg->duration &&
286  os->segments[i + repeat + 1]->time == os->segments[i + repeat]->time + os->segments[i + repeat]->duration)
287  repeat++;
288  if (repeat > 0)
289  avio_printf(out, "r=\"%d\" ", repeat);
290  avio_printf(out, "/>\n");
291  i += 1 + repeat;
292  cur_time += (1 + repeat) * seg->duration;
293  }
294  avio_printf(out, "\t\t\t\t\t</SegmentTimeline>\n");
295  }
296  avio_printf(out, "\t\t\t\t</SegmentTemplate>\n");
297  } else if (c->single_file) {
298  avio_printf(out, "\t\t\t\t<BaseURL>%s</BaseURL>\n", os->initfile);
299  avio_printf(out, "\t\t\t\t<SegmentList timescale=\"%d\" duration=\"%"PRId64"\" startNumber=\"%d\">\n", AV_TIME_BASE, c->last_duration, start_number);
300  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);
301  for (i = start_index; i < os->nb_segments; i++) {
302  Segment *seg = os->segments[i];
303  avio_printf(out, "\t\t\t\t\t<SegmentURL mediaRange=\"%"PRId64"-%"PRId64"\" ", seg->start_pos, seg->start_pos + seg->range_length - 1);
304  if (seg->index_length)
305  avio_printf(out, "indexRange=\"%"PRId64"-%"PRId64"\" ", seg->start_pos, seg->start_pos + seg->index_length - 1);
306  avio_printf(out, "/>\n");
307  }
308  avio_printf(out, "\t\t\t\t</SegmentList>\n");
309  } else {
310  avio_printf(out, "\t\t\t\t<SegmentList timescale=\"%d\" duration=\"%"PRId64"\" startNumber=\"%d\">\n", AV_TIME_BASE, c->last_duration, start_number);
311  avio_printf(out, "\t\t\t\t\t<Initialization sourceURL=\"%s\" />\n", os->initfile);
312  for (i = start_index; i < os->nb_segments; i++) {
313  Segment *seg = os->segments[i];
314  avio_printf(out, "\t\t\t\t\t<SegmentURL media=\"%s\" />\n", seg->file);
315  }
316  avio_printf(out, "\t\t\t\t</SegmentList>\n");
317  }
318 }
319 
320 static char *xmlescape(const char *str) {
321  int outlen = strlen(str)*3/2 + 6;
322  char *out = av_realloc(NULL, outlen + 1);
323  int pos = 0;
324  if (!out)
325  return NULL;
326  for (; *str; str++) {
327  if (pos + 6 > outlen) {
328  char *tmp;
329  outlen = 2 * outlen + 6;
330  tmp = av_realloc(out, outlen + 1);
331  if (!tmp) {
332  av_free(out);
333  return NULL;
334  }
335  out = tmp;
336  }
337  if (*str == '&') {
338  memcpy(&out[pos], "&amp;", 5);
339  pos += 5;
340  } else if (*str == '<') {
341  memcpy(&out[pos], "&lt;", 4);
342  pos += 4;
343  } else if (*str == '>') {
344  memcpy(&out[pos], "&gt;", 4);
345  pos += 4;
346  } else if (*str == '\'') {
347  memcpy(&out[pos], "&apos;", 6);
348  pos += 6;
349  } else if (*str == '\"') {
350  memcpy(&out[pos], "&quot;", 6);
351  pos += 6;
352  } else {
353  out[pos++] = *str;
354  }
355  }
356  out[pos] = '\0';
357  return out;
358 }
359 
360 static void write_time(AVIOContext *out, int64_t time)
361 {
362  int seconds = time / AV_TIME_BASE;
363  int fractions = time % AV_TIME_BASE;
364  int minutes = seconds / 60;
365  int hours = minutes / 60;
366  seconds %= 60;
367  minutes %= 60;
368  avio_printf(out, "PT");
369  if (hours)
370  avio_printf(out, "%dH", hours);
371  if (hours || minutes)
372  avio_printf(out, "%dM", minutes);
373  avio_printf(out, "%d.%dS", seconds, fractions / (AV_TIME_BASE / 10));
374 }
375 
376 static void format_date_now(char *buf, int size)
377 {
378  time_t t = time(NULL);
379  struct tm *ptm, tmbuf;
380  ptm = gmtime_r(&t, &tmbuf);
381  if (ptm) {
382  if (!strftime(buf, size, "%Y-%m-%dT%H:%M:%SZ", ptm))
383  buf[0] = '\0';
384  }
385 }
386 
388 {
389  DASHContext *c = s->priv_data;
390  AdaptationSet *as = &c->as[as_index];
391  AVDictionaryEntry *lang, *role;
392  int i;
393 
394  avio_printf(out, "\t\t<AdaptationSet id=\"%s\" contentType=\"%s\" segmentAlignment=\"true\" bitstreamSwitching=\"true\"",
395  as->id, as->media_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio");
397  avio_printf(out, " %s=\"%d/%d\"", (av_cmp_q(c->min_frame_rate, c->max_frame_rate) < 0) ? "maxFrameRate" : "frameRate", c->max_frame_rate.num, c->max_frame_rate.den);
398  lang = av_dict_get(as->metadata, "language", NULL, 0);
399  if (lang)
400  avio_printf(out, " lang=\"%s\"", lang->value);
401  avio_printf(out, ">\n");
402 
403  role = av_dict_get(as->metadata, "role", NULL, 0);
404  if (role)
405  avio_printf(out, "\t\t\t<Role schemeIdUri=\"urn:mpeg:dash:role:2011\" value=\"%s\"/>\n", role->value);
406 
407  for (i = 0; i < s->nb_streams; i++) {
408  OutputStream *os = &c->streams[i];
409 
410  if (os->as_idx - 1 != as_index)
411  continue;
412 
413  if (as->media_type == AVMEDIA_TYPE_VIDEO) {
414  AVStream *st = s->streams[i];
415  avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"video/%s\" codecs=\"%s\"%s width=\"%d\" height=\"%d\"",
416  i, os->format_name, os->codec_str, os->bandwidth_str, s->streams[i]->codecpar->width, s->streams[i]->codecpar->height);
417  if (st->avg_frame_rate.num)
418  avio_printf(out, " frameRate=\"%d/%d\"", st->avg_frame_rate.num, st->avg_frame_rate.den);
419  avio_printf(out, ">\n");
420  } else {
421  avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"audio/%s\" codecs=\"%s\"%s audioSamplingRate=\"%d\">\n",
422  i, os->format_name, os->codec_str, os->bandwidth_str, s->streams[i]->codecpar->sample_rate);
423  avio_printf(out, "\t\t\t\t<AudioChannelConfiguration schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\" value=\"%d\" />\n",
424  s->streams[i]->codecpar->channels);
425  }
426  output_segment_list(os, out, c);
427  avio_printf(out, "\t\t\t</Representation>\n");
428  }
429  avio_printf(out, "\t\t</AdaptationSet>\n");
430 
431  return 0;
432 }
433 
435 {
436  DASHContext *c = s->priv_data;
437 
438  void *mem = av_realloc(c->as, sizeof(*c->as) * (c->nb_as + 1));
439  if (!mem)
440  return AVERROR(ENOMEM);
441  c->as = mem;
442  ++c->nb_as;
443 
444  *as = &c->as[c->nb_as - 1];
445  memset(*as, 0, sizeof(**as));
446  (*as)->media_type = type;
447 
448  return 0;
449 }
450 
451 static int adaptation_set_add_stream(AVFormatContext *s, int as_idx, int i)
452 {
453  DASHContext *c = s->priv_data;
454  AdaptationSet *as = &c->as[as_idx - 1];
455  OutputStream *os = &c->streams[i];
456 
457  if (as->media_type != s->streams[i]->codecpar->codec_type) {
458  av_log(s, AV_LOG_ERROR, "Codec type of stream %d doesn't match AdaptationSet's media type\n", i);
459  return AVERROR(EINVAL);
460  } else if (os->as_idx) {
461  av_log(s, AV_LOG_ERROR, "Stream %d is already assigned to an AdaptationSet\n", i);
462  return AVERROR(EINVAL);
463  }
464  os->as_idx = as_idx;
465 
466  return 0;
467 }
468 
470 {
471  DASHContext *c = s->priv_data;
472  const char *p = c->adaptation_sets;
473  enum { new_set, parse_id, parsing_streams } state;
474  AdaptationSet *as;
475  int i, n, ret;
476 
477  // default: one AdaptationSet for each stream
478  if (!p) {
479  for (i = 0; i < s->nb_streams; i++) {
480  if ((ret = add_adaptation_set(s, &as, s->streams[i]->codecpar->codec_type)) < 0)
481  return ret;
482  snprintf(as->id, sizeof(as->id), "%d", i);
483 
484  c->streams[i].as_idx = c->nb_as;
485  }
486  goto end;
487  }
488 
489  // syntax id=0,streams=0,1,2 id=1,streams=3,4 and so on
490  state = new_set;
491  while (*p) {
492  if (*p == ' ') {
493  p++;
494  continue;
495  } else if (state == new_set && av_strstart(p, "id=", &p)) {
496 
497  if ((ret = add_adaptation_set(s, &as, AVMEDIA_TYPE_UNKNOWN)) < 0)
498  return ret;
499 
500  n = strcspn(p, ",");
501  snprintf(as->id, sizeof(as->id), "%.*s", n, p);
502 
503  p += n;
504  if (*p)
505  p++;
506  state = parse_id;
507  } else if (state == parse_id && av_strstart(p, "streams=", &p)) {
508  state = parsing_streams;
509  } else if (state == parsing_streams) {
510  AdaptationSet *as = &c->as[c->nb_as - 1];
511  char idx_str[8], *end_str;
512 
513  n = strcspn(p, " ,");
514  snprintf(idx_str, sizeof(idx_str), "%.*s", n, p);
515  p += n;
516 
517  // if value is "a" or "v", map all streams of that type
518  if (as->media_type == AVMEDIA_TYPE_UNKNOWN && (idx_str[0] == 'v' || idx_str[0] == 'a')) {
519  enum AVMediaType type = (idx_str[0] == 'v') ? AVMEDIA_TYPE_VIDEO : AVMEDIA_TYPE_AUDIO;
520  av_log(s, AV_LOG_DEBUG, "Map all streams of type %s\n", idx_str);
521 
522  for (i = 0; i < s->nb_streams; i++) {
523  if (s->streams[i]->codecpar->codec_type != type)
524  continue;
525 
526  as->media_type = s->streams[i]->codecpar->codec_type;
527 
528  if ((ret = adaptation_set_add_stream(s, c->nb_as, i)) < 0)
529  return ret;
530  }
531  } else { // select single stream
532  i = strtol(idx_str, &end_str, 10);
533  if (idx_str == end_str || i < 0 || i >= s->nb_streams) {
534  av_log(s, AV_LOG_ERROR, "Selected stream \"%s\" not found!\n", idx_str);
535  return AVERROR(EINVAL);
536  }
537  av_log(s, AV_LOG_DEBUG, "Map stream %d\n", i);
538 
539  if (as->media_type == AVMEDIA_TYPE_UNKNOWN) {
540  as->media_type = s->streams[i]->codecpar->codec_type;
541  }
542 
543  if ((ret = adaptation_set_add_stream(s, c->nb_as, i)) < 0)
544  return ret;
545  }
546 
547  if (*p == ' ')
548  state = new_set;
549  if (*p)
550  p++;
551  } else {
552  return AVERROR(EINVAL);
553  }
554  }
555 
556 end:
557  // check for unassigned streams
558  for (i = 0; i < s->nb_streams; i++) {
559  OutputStream *os = &c->streams[i];
560  if (!os->as_idx) {
561  av_log(s, AV_LOG_ERROR, "Stream %d is not mapped to an AdaptationSet\n", i);
562  return AVERROR(EINVAL);
563  }
564  }
565  return 0;
566 }
567 
568 static int write_manifest(AVFormatContext *s, int final)
569 {
570  DASHContext *c = s->priv_data;
571  AVIOContext *out;
572  char temp_filename[1024];
573  int ret, i;
574  const char *proto = avio_find_protocol_name(s->filename);
575  int use_rename = proto && !strcmp(proto, "file");
576  static unsigned int warned_non_file = 0;
577  AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
578 
579  if (!use_rename && !warned_non_file++)
580  av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this may lead to races and temporary partial files\n");
581 
582  snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", s->filename);
583  ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL);
584  if (ret < 0) {
585  av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
586  return ret;
587  }
588  avio_printf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
589  avio_printf(out, "<MPD xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
590  "\txmlns=\"urn:mpeg:dash:schema:mpd:2011\"\n"
591  "\txmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
592  "\txsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd\"\n"
593  "\tprofiles=\"urn:mpeg:dash:profile:isoff-live:2011\"\n"
594  "\ttype=\"%s\"\n", final ? "static" : "dynamic");
595  if (final) {
596  avio_printf(out, "\tmediaPresentationDuration=\"");
597  write_time(out, c->total_duration);
598  avio_printf(out, "\"\n");
599  } else {
600  int64_t update_period = c->last_duration / AV_TIME_BASE;
601  char now_str[100];
602  if (c->use_template && !c->use_timeline)
603  update_period = 500;
604  avio_printf(out, "\tminimumUpdatePeriod=\"PT%"PRId64"S\"\n", update_period);
605  avio_printf(out, "\tsuggestedPresentationDelay=\"PT%"PRId64"S\"\n", c->last_duration / AV_TIME_BASE);
606  if (!c->availability_start_time[0] && s->nb_streams > 0 && c->streams[0].nb_segments > 0) {
608  }
609  if (c->availability_start_time[0])
610  avio_printf(out, "\tavailabilityStartTime=\"%s\"\n", c->availability_start_time);
611  format_date_now(now_str, sizeof(now_str));
612  if (now_str[0])
613  avio_printf(out, "\tpublishTime=\"%s\"\n", now_str);
614  if (c->window_size && c->use_template) {
615  avio_printf(out, "\ttimeShiftBufferDepth=\"");
616  write_time(out, c->last_duration * c->window_size);
617  avio_printf(out, "\"\n");
618  }
619  }
620  avio_printf(out, "\tminBufferTime=\"");
621  write_time(out, c->last_duration * 2);
622  avio_printf(out, "\">\n");
623  avio_printf(out, "\t<ProgramInformation>\n");
624  if (title) {
625  char *escaped = xmlescape(title->value);
626  avio_printf(out, "\t\t<Title>%s</Title>\n", escaped);
627  av_free(escaped);
628  }
629  avio_printf(out, "\t</ProgramInformation>\n");
630  if (c->utc_timing_url)
631  avio_printf(out, "\t<UTCTiming schemeIdUri=\"urn:mpeg:dash:utc:http-xsdate:2014\" value=\"%s\"/>\n", c->utc_timing_url);
632 
633  if (c->window_size && s->nb_streams > 0 && c->streams[0].nb_segments > 0 && !c->use_template) {
634  OutputStream *os = &c->streams[0];
635  int start_index = FFMAX(os->nb_segments - c->window_size, 0);
636  int64_t start_time = av_rescale_q(os->segments[start_index]->time, s->streams[0]->time_base, AV_TIME_BASE_Q);
637  avio_printf(out, "\t<Period id=\"0\" start=\"");
638  write_time(out, start_time);
639  avio_printf(out, "\">\n");
640  } else {
641  avio_printf(out, "\t<Period id=\"0\" start=\"PT0.0S\">\n");
642  }
643 
644  for (i = 0; i < c->nb_as; i++) {
645  if ((ret = write_adaptation_set(s, out, i)) < 0)
646  return ret;
647  }
648  avio_printf(out, "\t</Period>\n");
649  avio_printf(out, "</MPD>\n");
650  avio_flush(out);
651  ff_format_io_close(s, &out);
652 
653  if (use_rename)
654  return avpriv_io_move(temp_filename, s->filename);
655 
656  return 0;
657 }
658 
659 static int dict_copy_entry(AVDictionary **dst, const AVDictionary *src, const char *key)
660 {
661  AVDictionaryEntry *entry = av_dict_get(src, key, NULL, 0);
662  if (entry)
663  av_dict_set(dst, key, entry->value, AV_DICT_DONT_OVERWRITE);
664  return 0;
665 }
666 
667 static int dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags)
668 {
669  char valuestr[22];
670  snprintf(valuestr, sizeof(valuestr), "%"PRId64, value);
671  flags &= ~AV_DICT_DONT_STRDUP_VAL;
672  return av_dict_set(pm, key, valuestr, flags);
673 }
674 
676 {
677  DASHContext *c = s->priv_data;
678  int ret = 0, i;
679  char *ptr;
680  char basename[1024];
681 
682  if (c->single_file_name)
683  c->single_file = 1;
684  if (c->single_file)
685  c->use_template = 0;
686  c->ambiguous_frame_rate = 0;
687 
688  av_strlcpy(c->dirname, s->filename, sizeof(c->dirname));
689  ptr = strrchr(c->dirname, '/');
690  if (ptr) {
691  av_strlcpy(basename, &ptr[1], sizeof(basename));
692  ptr[1] = '\0';
693  } else {
694  c->dirname[0] = '\0';
695  av_strlcpy(basename, s->filename, sizeof(basename));
696  }
697 
698  ptr = strrchr(basename, '.');
699  if (ptr)
700  *ptr = '\0';
701 
702  c->streams = av_mallocz(sizeof(*c->streams) * s->nb_streams);
703  if (!c->streams)
704  return AVERROR(ENOMEM);
705 
706  if ((ret = parse_adaptation_sets(s)) < 0)
707  return ret;
708 
709  for (i = 0; i < s->nb_streams; i++) {
710  OutputStream *os = &c->streams[i];
711  AdaptationSet *as = &c->as[os->as_idx - 1];
713  AVStream *st;
715  char filename[1024];
716 
717  os->bit_rate = s->streams[i]->codecpar->bit_rate;
718  if (os->bit_rate) {
719  snprintf(os->bandwidth_str, sizeof(os->bandwidth_str),
720  " bandwidth=\"%d\"", os->bit_rate);
721  } else {
724  av_log(s, level, "No bit rate set for stream %d\n", i);
726  return AVERROR(EINVAL);
727  }
728 
729  // copy AdaptationSet language and role from stream metadata
730  dict_copy_entry(&as->metadata, s->streams[i]->metadata, "language");
731  dict_copy_entry(&as->metadata, s->streams[i]->metadata, "role");
732 
733  ctx = avformat_alloc_context();
734  if (!ctx)
735  return AVERROR(ENOMEM);
736 
737  // choose muxer based on codec: webm for VP8/9 and opus, mp4 otherwise
738  // note: os->format_name is also used as part of the mimetype of the
739  // representation, e.g. video/<format_name>
740  if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_VP8 ||
744  snprintf(os->format_name, sizeof(os->format_name), "webm");
745  } else {
746  snprintf(os->format_name, sizeof(os->format_name), "mp4");
747  }
749  if (!ctx->oformat)
751  os->ctx = ctx;
753  ctx->opaque = s->opaque;
754  ctx->io_close = s->io_close;
755  ctx->io_open = s->io_open;
756 
757  if (!(st = avformat_new_stream(ctx, NULL)))
758  return AVERROR(ENOMEM);
761  st->time_base = s->streams[i]->time_base;
763  ctx->flags = s->flags;
764 
765  if ((ret = avio_open_dyn_buf(&ctx->pb)) < 0)
766  return ret;
767 
768  if (c->single_file) {
769  if (c->single_file_name)
770  ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), c->single_file_name, i, 0, os->bit_rate, 0);
771  else
772  snprintf(os->initfile, sizeof(os->initfile), "%s-stream%d.m4s", basename, i);
773  } else {
774  ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), c->init_seg_name, i, 0, os->bit_rate, 0);
775  }
776  snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile);
777  ret = s->io_open(s, &os->out, filename, AVIO_FLAG_WRITE, NULL);
778  if (ret < 0)
779  return ret;
780  os->init_start_pos = 0;
781 
782  if (!strcmp(os->format_name, "mp4")) {
783  av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0);
784  } else {
785  dict_set_int(&opts, "cluster_time_limit", c->min_seg_duration / 1000, 0);
786  dict_set_int(&opts, "cluster_size_limit", 5 * 1024 * 1024, 0); // set a large cluster size limit
787  }
788  if ((ret = avformat_write_header(ctx, &opts)) < 0)
789  return ret;
790  os->ctx_inited = 1;
791  avio_flush(ctx->pb);
792  av_dict_free(&opts);
793 
794  av_log(s, AV_LOG_VERBOSE, "Representation %d init segment will be written to: %s\n", i, filename);
795 
796  // Flush init segment
797  // except for mp4, since delay_moov is set and the init segment
798  // is then flushed after the first packets
799  if (strcmp(os->format_name, "mp4")) {
800  flush_init_segment(s, os);
801  }
802 
803  s->streams[i]->time_base = st->time_base;
804  // If the muxer wants to shift timestamps, request to have them shifted
805  // already before being handed to this muxer, so we don't have mismatches
806  // between the MPD and the actual segments.
808  if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
809  AVRational avg_frame_rate = s->streams[i]->avg_frame_rate;
810  if (avg_frame_rate.num > 0) {
811  if (av_cmp_q(avg_frame_rate, c->min_frame_rate) < 0)
812  c->min_frame_rate = avg_frame_rate;
813  if (av_cmp_q(c->max_frame_rate, avg_frame_rate) < 0)
814  c->max_frame_rate = avg_frame_rate;
815  } else {
816  c->ambiguous_frame_rate = 1;
817  }
818  c->has_video = 1;
819  }
820 
821  set_codec_str(s, st->codecpar, os->codec_str, sizeof(os->codec_str));
823  os->max_pts = AV_NOPTS_VALUE;
824  os->last_dts = AV_NOPTS_VALUE;
825  os->segment_index = 1;
826  }
827 
828  if (!c->has_video && c->min_seg_duration <= 0) {
829  av_log(s, AV_LOG_WARNING, "no video stream and no min seg duration set\n");
830  return AVERROR(EINVAL);
831  }
832  return 0;
833 }
834 
836 {
837  DASHContext *c = s->priv_data;
838  int i, ret;
839  for (i = 0; i < s->nb_streams; i++) {
840  OutputStream *os = &c->streams[i];
841  if ((ret = avformat_write_header(os->ctx, NULL)) < 0) {
842  dash_free(s);
843  return ret;
844  }
845  }
846  ret = write_manifest(s, 0);
847  if (!ret)
848  av_log(s, AV_LOG_VERBOSE, "Manifest written to: %s\n", s->filename);
849  return ret;
850 }
851 
852 static int add_segment(OutputStream *os, const char *file,
853  int64_t time, int duration,
854  int64_t start_pos, int64_t range_length,
855  int64_t index_length)
856 {
857  int err;
858  Segment *seg;
859  if (os->nb_segments >= os->segments_size) {
860  os->segments_size = (os->segments_size + 1) * 2;
861  if ((err = av_reallocp(&os->segments, sizeof(*os->segments) *
862  os->segments_size)) < 0) {
863  os->segments_size = 0;
864  os->nb_segments = 0;
865  return err;
866  }
867  }
868  seg = av_mallocz(sizeof(*seg));
869  if (!seg)
870  return AVERROR(ENOMEM);
871  av_strlcpy(seg->file, file, sizeof(seg->file));
872  seg->time = time;
873  seg->duration = duration;
874  if (seg->time < 0) { // If pts<0, it is expected to be cut away with an edit list
875  seg->duration += seg->time;
876  seg->time = 0;
877  }
878  seg->start_pos = start_pos;
879  seg->range_length = range_length;
880  seg->index_length = index_length;
881  os->segments[os->nb_segments++] = seg;
882  os->segment_index++;
883  return 0;
884 }
885 
886 static void write_styp(AVIOContext *pb)
887 {
888  avio_wb32(pb, 24);
889  ffio_wfourcc(pb, "styp");
890  ffio_wfourcc(pb, "msdh");
891  avio_wb32(pb, 0); /* minor */
892  ffio_wfourcc(pb, "msdh");
893  ffio_wfourcc(pb, "msix");
894 }
895 
896 static void find_index_range(AVFormatContext *s, const char *full_path,
897  int64_t pos, int *index_length)
898 {
899  uint8_t buf[8];
900  AVIOContext *pb;
901  int ret;
902 
903  ret = s->io_open(s, &pb, full_path, AVIO_FLAG_READ, NULL);
904  if (ret < 0)
905  return;
906  if (avio_seek(pb, pos, SEEK_SET) != pos) {
907  ff_format_io_close(s, &pb);
908  return;
909  }
910  ret = avio_read(pb, buf, 8);
911  ff_format_io_close(s, &pb);
912  if (ret < 8)
913  return;
914  if (AV_RL32(&buf[4]) != MKTAG('s', 'i', 'd', 'x'))
915  return;
916  *index_length = AV_RB32(&buf[0]);
917 }
918 
920  AVCodecParameters *par)
921 {
922  uint8_t *extradata;
923 
924  if (os->ctx->streams[0]->codecpar->extradata_size || !par->extradata_size)
925  return 0;
926 
927  extradata = av_malloc(par->extradata_size);
928 
929  if (!extradata)
930  return AVERROR(ENOMEM);
931 
932  memcpy(extradata, par->extradata, par->extradata_size);
933 
934  os->ctx->streams[0]->codecpar->extradata = extradata;
936 
937  set_codec_str(s, par, os->codec_str, sizeof(os->codec_str));
938 
939  return 0;
940 }
941 
942 static int dash_flush(AVFormatContext *s, int final, int stream)
943 {
944  DASHContext *c = s->priv_data;
945  int i, ret = 0;
946 
947  const char *proto = avio_find_protocol_name(s->filename);
948  int use_rename = proto && !strcmp(proto, "file");
949 
950  int cur_flush_segment_index = 0;
951  if (stream >= 0)
952  cur_flush_segment_index = c->streams[stream].segment_index;
953 
954  for (i = 0; i < s->nb_streams; i++) {
955  OutputStream *os = &c->streams[i];
956  char filename[1024] = "", full_path[1024], temp_path[1024];
957  int range_length, index_length = 0;
958 
959  if (!os->packets_written)
960  continue;
961 
962  // Flush the single stream that got a keyframe right now.
963  // Flush all audio streams as well, in sync with video keyframes,
964  // but not the other video streams.
965  if (stream >= 0 && i != stream) {
967  continue;
968  // Make sure we don't flush audio streams multiple times, when
969  // all video streams are flushed one at a time.
970  if (c->has_video && os->segment_index > cur_flush_segment_index)
971  continue;
972  }
973 
974  if (!os->init_range_length) {
975  flush_init_segment(s, os);
976  }
977 
978  if (!c->single_file) {
979  ff_dash_fill_tmpl_params(filename, sizeof(filename), c->media_seg_name, i, os->segment_index, os->bit_rate, os->start_pts);
980  snprintf(full_path, sizeof(full_path), "%s%s", c->dirname, filename);
981  snprintf(temp_path, sizeof(temp_path), use_rename ? "%s.tmp" : "%s", full_path);
982  ret = s->io_open(s, &os->out, temp_path, AVIO_FLAG_WRITE, NULL);
983  if (ret < 0)
984  break;
985  if (!strcmp(os->format_name, "mp4"))
986  write_styp(os->ctx->pb);
987  } else {
988  snprintf(full_path, sizeof(full_path), "%s%s", c->dirname, os->initfile);
989  }
990 
991  ret = flush_dynbuf(os, &range_length);
992  if (ret < 0)
993  break;
994  os->packets_written = 0;
995 
996  if (c->single_file) {
997  find_index_range(s, full_path, os->pos, &index_length);
998  } else {
999  ff_format_io_close(s, &os->out);
1000 
1001  if (use_rename) {
1002  ret = avpriv_io_move(temp_path, full_path);
1003  if (ret < 0)
1004  break;
1005  }
1006  }
1007 
1008  if (!os->bit_rate) {
1009  // calculate average bitrate of first segment
1010  int64_t bitrate = (int64_t) range_length * 8 * AV_TIME_BASE / (os->max_pts - os->start_pts);
1011  if (bitrate >= 0) {
1012  os->bit_rate = bitrate;
1013  snprintf(os->bandwidth_str, sizeof(os->bandwidth_str),
1014  " bandwidth=\"%d\"", os->bit_rate);
1015  }
1016  }
1017  add_segment(os, filename, os->start_pts, os->max_pts - os->start_pts, os->pos, range_length, index_length);
1018  av_log(s, AV_LOG_VERBOSE, "Representation %d media segment %d written to: %s\n", i, os->segment_index, full_path);
1019 
1020  os->pos += range_length;
1021  }
1022 
1023  if (c->window_size || (final && c->remove_at_exit)) {
1024  for (i = 0; i < s->nb_streams; i++) {
1025  OutputStream *os = &c->streams[i];
1026  int j;
1027  int remove = os->nb_segments - c->window_size - c->extra_window_size;
1028  if (final && c->remove_at_exit)
1029  remove = os->nb_segments;
1030  if (remove > 0) {
1031  for (j = 0; j < remove; j++) {
1032  char filename[1024];
1033  snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->segments[j]->file);
1034  unlink(filename);
1035  av_free(os->segments[j]);
1036  }
1037  os->nb_segments -= remove;
1038  memmove(os->segments, os->segments + remove, os->nb_segments * sizeof(*os->segments));
1039  }
1040  }
1041  }
1042 
1043  if (ret >= 0)
1044  ret = write_manifest(s, final);
1045  return ret;
1046 }
1047 
1049 {
1050  DASHContext *c = s->priv_data;
1051  AVStream *st = s->streams[pkt->stream_index];
1052  OutputStream *os = &c->streams[pkt->stream_index];
1053  int ret;
1054 
1055  ret = update_stream_extradata(s, os, st->codecpar);
1056  if (ret < 0)
1057  return ret;
1058 
1059  // Fill in a heuristic guess of the packet duration, if none is available.
1060  // The mp4 muxer will do something similar (for the last packet in a fragment)
1061  // if nothing is set (setting it for the other packets doesn't hurt).
1062  // By setting a nonzero duration here, we can be sure that the mp4 muxer won't
1063  // invoke its heuristic (this doesn't have to be identical to that algorithm),
1064  // so that we know the exact timestamps of fragments.
1065  if (!pkt->duration && os->last_dts != AV_NOPTS_VALUE)
1066  pkt->duration = pkt->dts - os->last_dts;
1067  os->last_dts = pkt->dts;
1068 
1069  // If forcing the stream to start at 0, the mp4 muxer will set the start
1070  // timestamps to 0. Do the same here, to avoid mismatches in duration/timestamps.
1071  if (os->first_pts == AV_NOPTS_VALUE &&
1073  pkt->pts -= pkt->dts;
1074  pkt->dts = 0;
1075  }
1076 
1077  if (os->first_pts == AV_NOPTS_VALUE)
1078  os->first_pts = pkt->pts;
1079 
1080  if ((!c->has_video || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) &&
1081  pkt->flags & AV_PKT_FLAG_KEY && os->packets_written &&
1082  av_compare_ts(pkt->pts - os->start_pts, st->time_base,
1083  c->min_seg_duration, AV_TIME_BASE_Q) >= 0) {
1084  int64_t prev_duration = c->last_duration;
1085 
1086  c->last_duration = av_rescale_q(pkt->pts - os->start_pts,
1087  st->time_base,
1088  AV_TIME_BASE_Q);
1089  c->total_duration = av_rescale_q(pkt->pts - os->first_pts,
1090  st->time_base,
1091  AV_TIME_BASE_Q);
1092 
1093  if ((!c->use_timeline || !c->use_template) && prev_duration) {
1094  if (c->last_duration < prev_duration*9/10 ||
1095  c->last_duration > prev_duration*11/10) {
1097  "Segment durations differ too much, enable use_timeline "
1098  "and use_template, or keep a stricter keyframe interval\n");
1099  }
1100  }
1101 
1102  if ((ret = dash_flush(s, 0, pkt->stream_index)) < 0)
1103  return ret;
1104  }
1105 
1106  if (!os->packets_written) {
1107  // If we wrote a previous segment, adjust the start time of the segment
1108  // to the end of the previous one (which is the same as the mp4 muxer
1109  // does). This avoids gaps in the timeline.
1110  if (os->max_pts != AV_NOPTS_VALUE)
1111  os->start_pts = os->max_pts;
1112  else
1113  os->start_pts = pkt->pts;
1114  }
1115  if (os->max_pts == AV_NOPTS_VALUE)
1116  os->max_pts = pkt->pts + pkt->duration;
1117  else
1118  os->max_pts = FFMAX(os->max_pts, pkt->pts + pkt->duration);
1119  os->packets_written++;
1120  return ff_write_chained(os->ctx, 0, pkt, s, 0);
1121 }
1122 
1124 {
1125  DASHContext *c = s->priv_data;
1126 
1127  if (s->nb_streams > 0) {
1128  OutputStream *os = &c->streams[0];
1129  // If no segments have been written so far, try to do a crude
1130  // guess of the segment duration
1131  if (!c->last_duration)
1133  s->streams[0]->time_base,
1134  AV_TIME_BASE_Q);
1136  s->streams[0]->time_base,
1137  AV_TIME_BASE_Q);
1138  }
1139  dash_flush(s, 1, -1);
1140 
1141  if (c->remove_at_exit) {
1142  char filename[1024];
1143  int i;
1144  for (i = 0; i < s->nb_streams; i++) {
1145  OutputStream *os = &c->streams[i];
1146  snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile);
1147  unlink(filename);
1148  }
1149  unlink(s->filename);
1150  }
1151 
1152  return 0;
1153 }
1154 
1155 static int dash_check_bitstream(struct AVFormatContext *s, const AVPacket *avpkt)
1156 {
1157  DASHContext *c = s->priv_data;
1158  OutputStream *os = &c->streams[avpkt->stream_index];
1159  AVFormatContext *oc = os->ctx;
1160  if (oc->oformat->check_bitstream) {
1161  int ret;
1162  AVPacket pkt = *avpkt;
1163  pkt.stream_index = 0;
1164  ret = oc->oformat->check_bitstream(oc, &pkt);
1165  if (ret == 1) {
1166  AVStream *st = s->streams[avpkt->stream_index];
1167  AVStream *ost = oc->streams[0];
1168  st->internal->bsfcs = ost->internal->bsfcs;
1169  st->internal->nb_bsfcs = ost->internal->nb_bsfcs;
1170  ost->internal->bsfcs = NULL;
1171  ost->internal->nb_bsfcs = 0;
1172  }
1173  return ret;
1174  }
1175  return 1;
1176 }
1177 
1178 #define OFFSET(x) offsetof(DASHContext, x)
1179 #define E AV_OPT_FLAG_ENCODING_PARAM
1180 static const AVOption options[] = {
1181  { "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 },
1182  { "window_size", "number of segments kept in the manifest", OFFSET(window_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, E },
1183  { "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 },
1184  { "min_seg_duration", "minimum segment duration (in microseconds)", OFFSET(min_seg_duration), AV_OPT_TYPE_INT64, { .i64 = 5000000 }, 0, INT_MAX, E },
1185  { "remove_at_exit", "remove all segments when finished", OFFSET(remove_at_exit), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1186  { "use_template", "Use SegmentTemplate instead of SegmentList", OFFSET(use_template), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },
1187  { "use_timeline", "Use SegmentTimeline in SegmentTemplate", OFFSET(use_timeline), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },
1188  { "single_file", "Store all segments in one file, accessed using byte ranges", OFFSET(single_file), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
1189  { "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 },
1190  { "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 },
1191  { "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 },
1192  { "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 },
1193  { NULL },
1194 };
1195 
1196 static const AVClass dash_class = {
1197  .class_name = "dash muxer",
1198  .item_name = av_default_item_name,
1199  .option = options,
1200  .version = LIBAVUTIL_VERSION_INT,
1201 };
1202 
1204  .name = "dash",
1205  .long_name = NULL_IF_CONFIG_SMALL("DASH Muxer"),
1206  .priv_data_size = sizeof(DASHContext),
1207  .audio_codec = AV_CODEC_ID_AAC,
1208  .video_codec = AV_CODEC_ID_H264,
1210  .init = dash_init,
1214  .deinit = dash_free,
1215  .check_bitstream = dash_check_bitstream,
1216  .priv_class = &dash_class,
1217 };
AVRational max_frame_rate
Definition: dashenc.c:100
static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int unqueue)
Definition: ffmpeg.c:671
#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:89
static int dict_copy_entry(AVDictionary **dst, const AVDictionary *src, const char *key)
Definition: dashenc.c:659
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition: avformat.h:1605
int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition: aviobuf.c:1342
AVOption.
Definition: opt.h:246
static int dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags)
Definition: dashenc.c:667
static int parse_adaptation_sets(AVFormatContext *s)
Definition: dashenc.c:469
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:86
static const AVOption options[]
Definition: dashenc.c:1180
static struct @260 state
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file.
Definition: mux.c:927
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
#define LIBAVUTIL_VERSION_INT
Definition: version.h:86
#define AV_DICT_DONT_OVERWRITE
Don't overwrite existing entries.
Definition: dict.h:79
int range_length
Definition: dashenc.c:48
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
static int64_t cur_time
Definition: ffserver.c:252
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:1372
int nb_segments
Definition: dashenc.c:69
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: avcodec.h:4152
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition: avformat.h:959
int num
Numerator.
Definition: rational.h:59
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:244
#define AVIO_FLAG_READ
read-only
Definition: avio.h:660
int n
Definition: dashenc.c:51
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:649
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:661
char codec_str[100]
Definition: dashenc.c:76
Convenience header that includes libavutil's core.
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:222
AVFormatContext * ctx
Definition: dashenc.c:61
int single_file
Definition: dashenc.c:90
static AVPacket pkt
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
static void output_segment_list(OutputStream *os, AVIOContext *out, DASHContext *c)
Definition: dashenc.c:258
#define src
Definition: vp8dsp.c:254
int packets_written
Definition: dashenc.c:65
int as_idx
Definition: dashenc.c:62
int64_t start_pts
Definition: dashenc.c:71
int avio_open_dyn_buf(AVIOContext **s)
Open a write only memory stream.
Definition: aviobuf.c:1313
int strict_std_compliance
Allow non-standard and experimental extension.
Definition: avformat.h:1635
static int dash_init(AVFormatContext *s)
Definition: dashenc.c:675
This struct describes the properties of an encoded stream.
Definition: avcodec.h:4144
int avpriv_io_move(const char *url_src, const char *url_dst)
Move or rename a resource.
Definition: avio.c:497
static struct codec_string codecs[]
int64_t last_dts
Definition: dashenc.c:72
static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_index)
Definition: dashenc.c:387
Format I/O context.
Definition: avformat.h:1349
int64_t init_start_pos
Definition: dashenc.c:67
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
static int64_t start_time
Definition: ffplay.c:327
char * adaptation_sets
Definition: dashenc.c:81
int mem
Definition: avisynth_c.h:821
AdaptationSet * as
Definition: dashenc.c:82
uint8_t
#define av_malloc(s)
int width
Video only.
Definition: avcodec.h:4218
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:434
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:1697
void ff_format_io_close(AVFormatContext *s, AVIOContext **pb)
Definition: utils.c:5449
int extra_window_size
Definition: dashenc.c:85
int ctx_inited
Definition: dashenc.c:62
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4367
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:1417
int64_t duration
Definition: movenc.c:63
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:1460
static int flags
Definition: log.c:57
uint32_t tag
Definition: movenc.c:1409
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
AVRational min_frame_rate
Definition: dashenc.c:100
ptrdiff_t size
Definition: opengl_enc.c:101
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:216
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:127
char initfile[1024]
Definition: dashenc.c:66
static void format_date_now(char *buf, int size)
Definition: dashenc.c:376
char format_name[8]
Definition: dashenc.c:64
#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:637
struct AVOutputFormat * oformat
The output container format.
Definition: avformat.h:1368
int64_t bit_rate
The average bitrate of the encoded data (in bits per second).
Definition: avcodec.h:4181
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: avcodec.h:1711
static void write_time(AVIOContext *out, int64_t time)
Definition: dashenc.c:360
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:568
#define E
Definition: dashenc.c:1179
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
Copy the contents of src to dst.
Definition: utils.c:2279
#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:1567
AVDictionary * metadata
Definition: dashenc.c:57
int remove_at_exit
Definition: dashenc.c:87
av_default_item_name
#define AVERROR(e)
Definition: error.h:43
int64_t last_duration
Definition: dashenc.c:93
static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
Definition: dashenc.c:1048
int nb_as
Definition: dashenc.c:83
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:179
int duration
Definition: dashenc.c:50
#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:4148
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:1155
static int flush_init_segment(AVFormatContext *s, OutputStream *os)
Definition: dashenc.c:213
int64_t start_pos
Definition: dashenc.c:47
AVRational avg_frame_rate
Average framerate.
Definition: avformat.h:970
#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:74
const AVCodecTag ff_mp4_obj_type[]
Definition: isom.c:34
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:1685
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:4170
void * opaque
User data.
Definition: avformat.h:1833
AVOutputFormat ff_dash_muxer
Definition: dashenc.c:1203
int ambiguous_frame_rate
Definition: dashenc.c:101
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition: avformat.h:1405
AVDictionary * opts
Definition: movenc.c:50
AVBSFContext ** bsfcs
bitstream filters to run on stream
Definition: internal.h:167
const char * media_seg_name
Definition: dashenc.c:99
int void avio_flush(AVIOContext *s)
Force flushing of buffered data.
Definition: aviobuf.c:236
char filename[1024]
input or output filename
Definition: avformat.h:1425
#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:528
int segment_index
Definition: dashenc.c:69
#define AV_DICT_DONT_STRDUP_VAL
Take ownership of a value that's been allocated with av_malloc() or another memory allocation functio...
Definition: dict.h:76
GLsizei GLboolean const GLfloat * value
Definition: opengl_enc.c:109
static int write_trailer(AVFormatContext *s1)
Definition: v4l2enc.c:94
#define AVFMT_GLOBALHEADER
Format wants global header.
Definition: avformat.h:485
const char * name
Definition: avformat.h:524
AVFormatContext * ctx
Definition: movenc.c:48
char dirname[1024]
Definition: dashenc.c:96
enum AVMediaType media_type
Definition: dashenc.c:56
int avoid_negative_ts
Avoid negative timestamps during muxing.
Definition: avformat.h:1658
int n
Definition: avisynth_c.h:684
AVDictionary * metadata
Definition: avformat.h:961
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:98
Usually treated as AVMEDIA_TYPE_DATA.
Definition: avutil.h:200
int64_t pos
Definition: dashenc.c:67
int segments_size
Definition: dashenc.c:69
#define OFFSET(x)
Definition: dashenc.c:1178
void ffio_free_dyn_buf(AVIOContext **s)
Free a dynamic buffer.
Definition: aviobuf.c:1372
Stream structure.
Definition: avformat.h:889
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:49
Segment ** segments
Definition: dashenc.c:70
int index_length
Definition: dashenc.c:48
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:1241
const AVCodecTag ff_codec_movaudio_tags[]
Definition: isom.c:311
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:260
AVIOContext * pb
I/O context.
Definition: avformat.h:1391
int bit_rate
Definition: dashenc.c:73
int use_template
Definition: dashenc.c:88
void * buf
Definition: avisynth_c.h:690
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:116
Describe the class of an AVClass context structure.
Definition: log.h:67
const char * init_seg_name
Definition: dashenc.c:98
Rational number (pair of numerator and denominator).
Definition: rational.h:58
AVMediaType
Definition: avutil.h:199
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition: avstring.c:101
#define FF_COMPLIANCE_STRICT
Strictly conform to all the things in the spec no matter what consequences.
Definition: avcodec.h:2983
#define snprintf
Definition: snprintf.h:34
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition: utils.c:4302
static int adaptation_set_add_stream(AVFormatContext *s, int as_idx, int i)
Definition: dashenc.c:451
int64_t total_duration
Definition: dashenc.c:94
static void find_index_range(AVFormatContext *s, const char *full_path, int64_t pos, int *index_length)
Definition: dashenc.c:896
char file[1024]
Definition: dashenc.c:46
const char * avio_find_protocol_name(const char *url)
Return the name of the protocol that will handle the passed URL.
Definition: avio.c:471
static int flush_dynbuf(OutputStream *os, int *range_length)
Definition: dashenc.c:191
uint8_t level
Definition: svq3.c:207
OutputStream * streams
Definition: dashenc.c:91
int init_range_length
Definition: dashenc.c:68
int sample_rate
Audio only.
Definition: avcodec.h:4262
#define AVFMT_AVOID_NEG_TS_MAKE_ZERO
Shift timestamps so that they start at 0.
Definition: avformat.h:1661
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
Main libavformat public API header.
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:478
Utilties for rational number calculation.
const char * single_file_name
Definition: dashenc.c:97
static double c[64]
int den
Denominator.
Definition: rational.h:60
static void write_styp(AVIOContext *pb)
Definition: dashenc.c:886
static int dash_write_header(AVFormatContext *s)
Definition: dashenc.c:835
char id[10]
Definition: dashenc.c:55
#define av_free(p)
char * value
Definition: dict.h:87
const char * str
Definition: dashenc.c:107
void * priv_data
Format private data.
Definition: avformat.h:1377
const char * utc_timing_url
Definition: dashenc.c:102
static int dash_write_trailer(AVFormatContext *s)
Definition: dashenc.c:1123
int window_size
Definition: dashenc.c:84
static void write_header(FFV1Context *f)
Definition: ffv1enc.c:337
static void dash_free(AVFormatContext *s)
Definition: dashenc.c:228
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: avcodec.h:4166
int has_video
Definition: dashenc.c:92
int channels
Audio only.
Definition: avcodec.h:4258
int64_t max_pts
Definition: dashenc.c:71
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed...
Definition: avcodec.h:1678
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
Definition: mux.c:1301
void avio_wb32(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:382
FILE * out
Definition: movenc.c:54
#define av_freep(p)
static int update_stream_extradata(AVFormatContext *s, OutputStream *os, AVCodecParameters *par)
Definition: dashenc.c:919
unbuffered private I/O API
#define AVERROR_MUXER_NOT_FOUND
Muxer not found.
Definition: error.h:60
AVCodecParameters * codecpar
Definition: avformat.h:1252
static char * xmlescape(const char *str)
Definition: dashenc.c:320
AVIOContext * out
Definition: dashenc.c:63
static int dash_flush(AVFormatContext *s, int final, int stream)
Definition: dashenc.c:942
int stream_index
Definition: avcodec.h:1681
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avformat.h:926
int64_t first_pts
Definition: ffmpeg.h:462
#define MKTAG(a, b, c, d)
Definition: common.h:342
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:501
int(* io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags, AVDictionary **options)
Definition: avformat.h:1909
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Definition: bytestream.h:87
This structure stores compressed data.
Definition: avcodec.h:1656
void(* io_close)(struct AVFormatContext *s, AVIOContext *pb)
A callback for closing the streams opened with AVFormatContext.io_open().
Definition: avformat.h:1915
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:1672
int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len)
Definition: avc.c:106
static const AVClass dash_class
Definition: dashenc.c:1196
#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:431
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:852
static uint8_t tmp[11]
Definition: aes_ctr.c:26