FFmpeg
smoothstreamingenc.c
Go to the documentation of this file.
1 /*
2  * Live smooth streaming fragmenter
3  * Copyright (c) 2012 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 "avformat.h"
28 #include "internal.h"
29 #include "mux.h"
30 #include "os_support.h"
31 #include "avc.h"
32 #include "url.h"
33 
34 #include "libavutil/mem.h"
35 #include "libavutil/opt.h"
36 #include "libavutil/avstring.h"
37 #include "libavutil/mathematics.h"
38 #include "libavutil/uuid.h"
39 
40 typedef struct Fragment {
42  int n;
44  char file[1024];
45  char infofile[1024];
46 } Fragment;
47 
48 typedef struct OutputStream {
50  URLContext *out; // Current output stream where all output is written
51  URLContext *out2; // Auxiliary output stream where all output is also written
52  URLContext *tail_out; // The actual main output stream, if we're currently seeked back to write elsewhere
54  int packets_written;
55  const char *stream_type_tag;
58 
59  const char *fourcc;
60  char *private_str;
62  int audio_tag;
63  char dirname[1024];
64  uint8_t iobuf[32768];
65 } OutputStream;
66 
67 typedef struct SmoothStreamingContext {
68  const AVClass *class; /* Class for private options. */
78 
79 static int ism_write(void *opaque, const uint8_t *buf, int buf_size)
80 {
81  OutputStream *os = opaque;
82  if (os->out)
83  ffurl_write(os->out, buf, buf_size);
84  if (os->out2)
85  ffurl_write(os->out2, buf, buf_size);
86  os->cur_pos += buf_size;
87  if (os->cur_pos >= os->tail_pos)
88  os->tail_pos = os->cur_pos;
89  return buf_size;
90 }
91 
92 static int64_t ism_seek(void *opaque, int64_t offset, int whence)
93 {
94  OutputStream *os = opaque;
95  int i;
96  if (whence != SEEK_SET)
97  return AVERROR(ENOSYS);
98  if (os->tail_out) {
99  ffurl_closep(&os->out);
100  ffurl_closep(&os->out2);
101  os->out = os->tail_out;
102  os->tail_out = NULL;
103  }
104  if (offset >= os->cur_start_pos) {
105  if (os->out)
106  ffurl_seek(os->out, offset - os->cur_start_pos, SEEK_SET);
107  os->cur_pos = offset;
108  return offset;
109  }
110  for (i = os->nb_fragments - 1; i >= 0; i--) {
111  Fragment *frag = os->fragments[i];
112  if (offset >= frag->start_pos && offset < frag->start_pos + frag->size) {
113  int ret;
115  os->tail_out = os->out;
116  av_dict_set(&opts, "truncate", "0", 0);
119  av_dict_free(&opts);
120  if (ret < 0) {
121  os->out = os->tail_out;
122  os->tail_out = NULL;
123  return ret;
124  }
125  av_dict_set(&opts, "truncate", "0", 0);
128  av_dict_free(&opts);
129  ffurl_seek(os->out, offset - frag->start_pos, SEEK_SET);
130  if (os->out2)
131  ffurl_seek(os->out2, offset - frag->start_pos, SEEK_SET);
132  os->cur_pos = offset;
133  return offset;
134  }
135  }
136  return AVERROR(EIO);
137 }
138 
140 {
141  AVCodecParameters *par = os->ctx->streams[0]->codecpar;
142  uint8_t *ptr = par->extradata;
143  int size = par->extradata_size;
144  int i;
145  if (par->codec_id == AV_CODEC_ID_H264) {
146  ff_avc_write_annexb_extradata(ptr, &ptr, &size);
147  if (!ptr)
148  ptr = par->extradata;
149  }
150  if (!ptr)
151  return;
152  os->private_str = av_mallocz(2*size + 1);
153  if (!os->private_str)
154  goto fail;
155  for (i = 0; i < size; i++)
156  snprintf(&os->private_str[2*i], 3, "%02x", ptr[i]);
157 fail:
158  if (ptr != par->extradata)
159  av_free(ptr);
160 }
161 
163 {
164  SmoothStreamingContext *c = s->priv_data;
165  int i, j;
166  if (!c->streams)
167  return;
168  for (i = 0; i < s->nb_streams; i++) {
169  OutputStream *os = &c->streams[i];
170  ffurl_closep(&os->out);
171  ffurl_closep(&os->out2);
172  ffurl_closep(&os->tail_out);
173  if (os->ctx && os->ctx->pb)
174  avio_context_free(&os->ctx->pb);
176  av_freep(&os->private_str);
177  for (j = 0; j < os->nb_fragments; j++)
178  av_freep(&os->fragments[j]);
179  av_freep(&os->fragments);
180  }
181  av_freep(&c->streams);
182 }
183 
184 static void output_chunk_list(OutputStream *os, AVIOContext *out, int final, int skip, int window_size)
185 {
186  int removed = 0, i, start = 0;
187  if (os->nb_fragments <= 0)
188  return;
189  if (os->fragments[0]->n > 0)
190  removed = 1;
191  if (final)
192  skip = 0;
193  if (window_size)
194  start = FFMAX(os->nb_fragments - skip - window_size, 0);
195  for (i = start; i < os->nb_fragments - skip; i++) {
196  Fragment *frag = os->fragments[i];
197  if (!final || removed)
198  avio_printf(out, "<c t=\"%"PRIu64"\" d=\"%"PRIu64"\" />\n", frag->start_time, frag->duration);
199  else
200  avio_printf(out, "<c n=\"%d\" d=\"%"PRIu64"\" />\n", frag->n, frag->duration);
201  }
202 }
203 
204 static int write_manifest(AVFormatContext *s, int final)
205 {
206  SmoothStreamingContext *c = s->priv_data;
207  AVIOContext *out;
208  char filename[1024], temp_filename[1024];
209  int ret, i, video_chunks = 0, audio_chunks = 0, video_streams = 0, audio_streams = 0;
210  int64_t duration = 0;
211 
212  snprintf(filename, sizeof(filename), "%s/Manifest", s->url);
213  snprintf(temp_filename, sizeof(temp_filename), "%s/Manifest.tmp", s->url);
214  ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL);
215  if (ret < 0) {
216  av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
217  return ret;
218  }
219  avio_printf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
220  for (i = 0; i < s->nb_streams; i++) {
221  OutputStream *os = &c->streams[i];
222  if (os->nb_fragments > 0) {
223  Fragment *last = os->fragments[os->nb_fragments - 1];
224  duration = last->start_time + last->duration;
225  }
226  if (s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
227  video_chunks = os->nb_fragments;
228  video_streams++;
229  } else {
230  audio_chunks = os->nb_fragments;
231  audio_streams++;
232  }
233  }
234  if (!final) {
235  duration = 0;
236  video_chunks = audio_chunks = 0;
237  }
238  if (c->window_size) {
239  video_chunks = FFMIN(video_chunks, c->window_size);
240  audio_chunks = FFMIN(audio_chunks, c->window_size);
241  }
242  avio_printf(out, "<SmoothStreamingMedia MajorVersion=\"2\" MinorVersion=\"0\" Duration=\"%"PRIu64"\"", duration);
243  if (!final)
244  avio_printf(out, " IsLive=\"true\" LookAheadFragmentCount=\"%d\" DVRWindowLength=\"0\"", c->lookahead_count);
245  avio_printf(out, ">\n");
246  if (c->has_video) {
247  int last = -1, index = 0;
248  avio_printf(out, "<StreamIndex Type=\"video\" QualityLevels=\"%d\" Chunks=\"%d\" Url=\"QualityLevels({bitrate})/Fragments(video={start time})\">\n", video_streams, video_chunks);
249  for (i = 0; i < s->nb_streams; i++) {
250  OutputStream *os = &c->streams[i];
251  if (s->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)
252  continue;
253  last = i;
254  avio_printf(out, "<QualityLevel Index=\"%d\" Bitrate=\"%"PRId64"\" FourCC=\"%s\" MaxWidth=\"%d\" MaxHeight=\"%d\" CodecPrivateData=\"%s\" />\n", index, s->streams[i]->codecpar->bit_rate, os->fourcc, s->streams[i]->codecpar->width, s->streams[i]->codecpar->height, os->private_str);
255  index++;
256  }
257  output_chunk_list(&c->streams[last], out, final, c->lookahead_count, c->window_size);
258  avio_printf(out, "</StreamIndex>\n");
259  }
260  if (c->has_audio) {
261  int last = -1, index = 0;
262  avio_printf(out, "<StreamIndex Type=\"audio\" QualityLevels=\"%d\" Chunks=\"%d\" Url=\"QualityLevels({bitrate})/Fragments(audio={start time})\">\n", audio_streams, audio_chunks);
263  for (i = 0; i < s->nb_streams; i++) {
264  OutputStream *os = &c->streams[i];
265  if (s->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
266  continue;
267  last = i;
268  avio_printf(out, "<QualityLevel Index=\"%d\" Bitrate=\"%"PRId64"\" FourCC=\"%s\" SamplingRate=\"%d\" Channels=\"%d\" BitsPerSample=\"16\" PacketSize=\"%d\" AudioTag=\"%d\" CodecPrivateData=\"%s\" />\n",
269  index, s->streams[i]->codecpar->bit_rate, os->fourcc, s->streams[i]->codecpar->sample_rate,
270  s->streams[i]->codecpar->ch_layout.nb_channels, os->packet_size, os->audio_tag, os->private_str);
271  index++;
272  }
273  output_chunk_list(&c->streams[last], out, final, c->lookahead_count, c->window_size);
274  avio_printf(out, "</StreamIndex>\n");
275  }
276  avio_printf(out, "</SmoothStreamingMedia>\n");
277  avio_flush(out);
279  return ff_rename(temp_filename, filename, s);
280 }
281 
283 {
284  SmoothStreamingContext *c = s->priv_data;
285  int ret = 0, i;
286  const AVOutputFormat *oformat;
287 
288  if (mkdir(s->url, 0777) == -1 && errno != EEXIST) {
289  av_log(s, AV_LOG_ERROR, "mkdir failed\n");
290  return AVERROR(errno);
291  }
292 
293  oformat = av_guess_format("ismv", NULL, NULL);
294  if (!oformat) {
296  }
297 
298  c->streams = av_calloc(s->nb_streams, sizeof(*c->streams));
299  if (!c->streams) {
300  return AVERROR(ENOMEM);
301  }
302 
303  for (i = 0; i < s->nb_streams; i++) {
304  OutputStream *os = &c->streams[i];
306  AVStream *st;
308 
309  if (!s->streams[i]->codecpar->bit_rate) {
310  av_log(s, AV_LOG_WARNING, "No bit rate set for stream %d\n", i);
311  // create a tmp name for the directory of fragments
312  snprintf(os->dirname, sizeof(os->dirname), "%s/QualityLevels(Tmp_%d)", s->url, i);
313  } else {
314  snprintf(os->dirname, sizeof(os->dirname), "%s/QualityLevels(%"PRId64")", s->url, s->streams[i]->codecpar->bit_rate);
315  }
316 
317  if (mkdir(os->dirname, 0777) == -1 && errno != EEXIST) {
318  av_log(s, AV_LOG_ERROR, "mkdir failed\n");
319  return AVERROR(errno);
320  }
321 
322  os->ctx = ctx = avformat_alloc_context();
323  if (!ctx) {
324  return AVERROR(ENOMEM);
325  }
326  if ((ret = ff_copy_whiteblacklists(ctx, s)) < 0)
327  return ret;
328  ctx->oformat = oformat;
329  ctx->interrupt_callback = s->interrupt_callback;
330 
331  if (!(st = avformat_new_stream(ctx, NULL))) {
332  return AVERROR(ENOMEM);
333  }
334  if ((ret = avcodec_parameters_copy(st->codecpar, s->streams[i]->codecpar)) < 0) {
335  return ret;
336  }
337  st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio;
338  st->time_base = s->streams[i]->time_base;
339 
340  ctx->pb = avio_alloc_context(os->iobuf, sizeof(os->iobuf), 1, os, NULL, ism_write, ism_seek);
341  if (!ctx->pb) {
342  return AVERROR(ENOMEM);
343  }
344 
345  av_dict_set_int(&opts, "ism_lookahead", c->lookahead_count, 0);
346  av_dict_set(&opts, "movflags", "+frag_custom", 0);
348  av_dict_free(&opts);
349  if (ret < 0) {
350  return ret;
351  }
352  avio_flush(ctx->pb);
353  s->streams[i]->time_base = st->time_base;
354  if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
355  c->has_video = 1;
356  os->stream_type_tag = "video";
357  if (st->codecpar->codec_id == AV_CODEC_ID_H264) {
358  os->fourcc = "H264";
359  } else if (st->codecpar->codec_id == AV_CODEC_ID_VC1) {
360  os->fourcc = "WVC1";
361  } else {
362  av_log(s, AV_LOG_ERROR, "Unsupported video codec\n");
363  return AVERROR(EINVAL);
364  }
365  } else {
366  c->has_audio = 1;
367  os->stream_type_tag = "audio";
368  if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
369  os->fourcc = "AACL";
370  os->audio_tag = 0xff;
371  } else if (st->codecpar->codec_id == AV_CODEC_ID_WMAPRO) {
372  os->fourcc = "WMAP";
373  os->audio_tag = 0x0162;
374  } else {
375  av_log(s, AV_LOG_ERROR, "Unsupported audio codec\n");
376  return AVERROR(EINVAL);
377  }
378  os->packet_size = st->codecpar->block_align ? st->codecpar->block_align : 4;
379  }
380  get_private_data(os);
381  }
382 
383  if (!c->has_video && c->min_frag_duration <= 0) {
384  av_log(s, AV_LOG_WARNING, "no video stream and no min frag duration set\n");
385  return AVERROR(EINVAL);
386  }
387  ret = write_manifest(s, 0);
388  if (ret < 0)
389  return ret;
390 
391  return 0;
392 }
393 
394 static int parse_fragment(AVFormatContext *s, const char *filename, int64_t *start_ts, int64_t *duration, int64_t *moof_size, int64_t size)
395 {
396  AVIOContext *in;
397  int ret;
398  uint32_t len;
399  if ((ret = s->io_open(s, &in, filename, AVIO_FLAG_READ, NULL)) < 0)
400  return ret;
401  ret = AVERROR(EIO);
402  *moof_size = avio_rb32(in);
403  if (*moof_size < 8 || *moof_size > size)
404  goto fail;
405  if (avio_rl32(in) != MKTAG('m','o','o','f'))
406  goto fail;
407  len = avio_rb32(in);
408  if (len > *moof_size)
409  goto fail;
410  if (avio_rl32(in) != MKTAG('m','f','h','d'))
411  goto fail;
412  avio_seek(in, len - 8, SEEK_CUR);
413  avio_rb32(in); /* traf size */
414  if (avio_rl32(in) != MKTAG('t','r','a','f'))
415  goto fail;
416  while (avio_tell(in) < *moof_size) {
417  uint32_t len = avio_rb32(in);
418  uint32_t tag = avio_rl32(in);
419  int64_t end = avio_tell(in) + len - 8;
420  if (len < 8 || len >= *moof_size)
421  goto fail;
422  if (tag == MKTAG('u','u','i','d')) {
423  static const AVUUID tfxd = {
424  0x6d, 0x1d, 0x9b, 0x05, 0x42, 0xd5, 0x44, 0xe6,
425  0x80, 0xe2, 0x14, 0x1d, 0xaf, 0xf7, 0x57, 0xb2
426  };
427  AVUUID uuid;
428  avio_read(in, uuid, 16);
429  if (av_uuid_equal(uuid, tfxd) && len >= 8 + 16 + 4 + 16) {
430  avio_seek(in, 4, SEEK_CUR);
431  *start_ts = avio_rb64(in);
432  *duration = avio_rb64(in);
433  ret = 0;
434  break;
435  }
436  }
437  avio_seek(in, end, SEEK_SET);
438  }
439 fail:
440  ff_format_io_close(s, &in);
441  return ret;
442 }
443 
444 static int add_fragment(OutputStream *os, const char *file, const char *infofile, int64_t start_time, int64_t duration, int64_t start_pos, int64_t size)
445 {
446  int err;
447  Fragment *frag;
448  if (os->nb_fragments >= os->fragments_size) {
449  os->fragments_size = (os->fragments_size + 1) * 2;
450  if ((err = av_reallocp_array(&os->fragments, sizeof(*os->fragments),
451  os->fragments_size)) < 0) {
452  os->fragments_size = 0;
453  os->nb_fragments = 0;
454  return err;
455  }
456  }
457  frag = av_mallocz(sizeof(*frag));
458  if (!frag)
459  return AVERROR(ENOMEM);
460  av_strlcpy(frag->file, file, sizeof(frag->file));
461  av_strlcpy(frag->infofile, infofile, sizeof(frag->infofile));
462  frag->start_time = start_time;
463  frag->duration = duration;
464  frag->start_pos = start_pos;
465  frag->size = size;
466  frag->n = os->fragment_index;
467  os->fragments[os->nb_fragments++] = frag;
468  os->fragment_index++;
469  return 0;
470 }
471 
472 static int copy_moof(AVFormatContext *s, const char* infile, const char *outfile, int64_t size)
473 {
474  AVIOContext *in, *out;
475  int ret = 0;
476  if ((ret = s->io_open(s, &in, infile, AVIO_FLAG_READ, NULL)) < 0)
477  return ret;
478  if ((ret = s->io_open(s, &out, outfile, AVIO_FLAG_WRITE, NULL)) < 0) {
479  ff_format_io_close(s, &in);
480  return ret;
481  }
482  while (size > 0) {
483  uint8_t buf[8192];
484  int n = FFMIN(size, sizeof(buf));
485  n = avio_read(in, buf, n);
486  if (n <= 0) {
487  ret = AVERROR(EIO);
488  break;
489  }
490  avio_write(out, buf, n);
491  size -= n;
492  }
493  avio_flush(out);
495  ff_format_io_close(s, &in);
496  return ret;
497 }
498 
499 static int ism_flush(AVFormatContext *s, int final)
500 {
501  SmoothStreamingContext *c = s->priv_data;
502  int i, ret = 0;
503 
504  for (i = 0; i < s->nb_streams; i++) {
505  OutputStream *os = &c->streams[i];
506  char filename[1024], target_filename[1024], header_filename[1024], curr_dirname[1024];
507  int64_t size;
508  int64_t start_ts, duration, moof_size;
509  if (!os->packets_written)
510  continue;
511 
512  snprintf(filename, sizeof(filename), "%s/temp", os->dirname);
513  ret = ffurl_open_whitelist(&os->out, filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL, s->protocol_whitelist, s->protocol_blacklist, NULL);
514  if (ret < 0)
515  break;
516  os->cur_start_pos = os->tail_pos;
517  av_write_frame(os->ctx, NULL);
518  avio_flush(os->ctx->pb);
519  os->packets_written = 0;
520  if (!os->out || os->tail_out)
521  return AVERROR(EIO);
522 
523  ffurl_closep(&os->out);
524  size = os->tail_pos - os->cur_start_pos;
525  if ((ret = parse_fragment(s, filename, &start_ts, &duration, &moof_size, size)) < 0)
526  break;
527 
528  if (!s->streams[i]->codecpar->bit_rate) {
529  int64_t bitrate = (int64_t) size * 8 * AV_TIME_BASE / av_rescale_q(duration, s->streams[i]->time_base, AV_TIME_BASE_Q);
530  if (!bitrate) {
531  av_log(s, AV_LOG_ERROR, "calculating bitrate got zero.\n");
532  ret = AVERROR(EINVAL);
533  return ret;
534  }
535 
536  av_log(s, AV_LOG_DEBUG, "calculated bitrate: %"PRId64"\n", bitrate);
537  s->streams[i]->codecpar->bit_rate = bitrate;
538  memcpy(curr_dirname, os->dirname, sizeof(os->dirname));
539  snprintf(os->dirname, sizeof(os->dirname), "%s/QualityLevels(%"PRId64")", s->url, s->streams[i]->codecpar->bit_rate);
540  snprintf(filename, sizeof(filename), "%s/temp", os->dirname);
541 
542  // rename the tmp folder back to the correct name since we now have the bitrate
543  if ((ret = ff_rename((const char*)curr_dirname, os->dirname, s)) < 0)
544  return ret;
545  }
546 
547  snprintf(header_filename, sizeof(header_filename), "%s/FragmentInfo(%s=%"PRIu64")", os->dirname, os->stream_type_tag, start_ts);
548  snprintf(target_filename, sizeof(target_filename), "%s/Fragments(%s=%"PRIu64")", os->dirname, os->stream_type_tag, start_ts);
549  copy_moof(s, filename, header_filename, moof_size);
550  ret = ff_rename(filename, target_filename, s);
551  if (ret < 0)
552  break;
553  add_fragment(os, target_filename, header_filename, start_ts, duration,
554  os->cur_start_pos, size);
555  }
556 
557  if (c->window_size || (final && c->remove_at_exit)) {
558  for (i = 0; i < s->nb_streams; i++) {
559  OutputStream *os = &c->streams[i];
560  int j;
561  int remove = os->nb_fragments - c->window_size - c->extra_window_size - c->lookahead_count;
562  if (final && c->remove_at_exit)
563  remove = os->nb_fragments;
564  if (remove > 0) {
565  for (j = 0; j < remove; j++) {
566  unlink(os->fragments[j]->file);
567  unlink(os->fragments[j]->infofile);
568  av_freep(&os->fragments[j]);
569  }
570  os->nb_fragments -= remove;
571  memmove(os->fragments, os->fragments + remove, os->nb_fragments * sizeof(*os->fragments));
572  }
573  if (final && c->remove_at_exit)
574  rmdir(os->dirname);
575  }
576  }
577 
578  if (ret >= 0)
579  ret = write_manifest(s, final);
580  return ret;
581 }
582 
584 {
585  SmoothStreamingContext *c = s->priv_data;
586  AVStream *st = s->streams[pkt->stream_index];
587  FFStream *const sti = ffstream(st);
588  OutputStream *os = &c->streams[pkt->stream_index];
589  int64_t end_dts = (c->nb_fragments + 1) * (int64_t) c->min_frag_duration;
590  int ret;
591 
592  if (sti->first_dts == AV_NOPTS_VALUE)
593  sti->first_dts = pkt->dts;
594 
595  if ((!c->has_video || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) &&
596  av_compare_ts(pkt->dts - sti->first_dts, st->time_base,
597  end_dts, AV_TIME_BASE_Q) >= 0 &&
599 
600  if ((ret = ism_flush(s, 0)) < 0)
601  return ret;
602  c->nb_fragments++;
603  }
604 
605  os->packets_written++;
606  return ff_write_chained(os->ctx, 0, pkt, s, 0);
607 }
608 
610 {
611  SmoothStreamingContext *c = s->priv_data;
612  ism_flush(s, 1);
613 
614  if (c->remove_at_exit) {
615  char filename[1024];
616  snprintf(filename, sizeof(filename), "%s/Manifest", s->url);
617  unlink(filename);
618  rmdir(s->url);
619  }
620 
621  return 0;
622 }
623 
624 #define OFFSET(x) offsetof(SmoothStreamingContext, x)
625 #define E AV_OPT_FLAG_ENCODING_PARAM
626 static const AVOption options[] = {
627  { "window_size", "number of fragments kept in the manifest", OFFSET(window_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, E },
628  { "extra_window_size", "number of fragments kept outside of the manifest before removing from disk", OFFSET(extra_window_size), AV_OPT_TYPE_INT, { .i64 = 5 }, 0, INT_MAX, E },
629  { "lookahead_count", "number of lookahead fragments", OFFSET(lookahead_count), AV_OPT_TYPE_INT, { .i64 = 2 }, 0, INT_MAX, E },
630  { "min_frag_duration", "minimum fragment duration (in microseconds)", OFFSET(min_frag_duration), AV_OPT_TYPE_INT64, { .i64 = 5000000 }, 0, INT_MAX, E },
631  { "remove_at_exit", "remove all fragments when finished", OFFSET(remove_at_exit), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
632  { NULL },
633 };
634 
635 static const AVClass ism_class = {
636  .class_name = "smooth streaming muxer",
637  .item_name = av_default_item_name,
638  .option = options,
639  .version = LIBAVUTIL_VERSION_INT,
640 };
641 
642 
644  .p.name = "smoothstreaming",
645  .p.long_name = NULL_IF_CONFIG_SMALL("Smooth Streaming Muxer"),
646  .p.audio_codec = AV_CODEC_ID_AAC,
647  .p.video_codec = AV_CODEC_ID_H264,
648  .p.flags = AVFMT_GLOBALHEADER | AVFMT_NOFILE,
649  .p.priv_class = &ism_class,
650  .priv_data_size = sizeof(SmoothStreamingContext),
654  .deinit = ism_free,
655 };
ffurl_seek
static int64_t ffurl_seek(URLContext *h, int64_t pos, int whence)
Change the position that will be used by the next read/write operation on the resource accessed by h.
Definition: url.h:222
SmoothStreamingContext::remove_at_exit
int remove_at_exit
Definition: smoothstreamingenc.c:73
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:215
AVCodecParameters::extradata
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: codec_par.h:69
OutputStream::cur_start_pos
int64_t cur_start_pos
Definition: smoothstreamingenc.c:53
AVOutputFormat::name
const char * name
Definition: avformat.h:510
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
AVCodecParameters::codec_type
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:51
av_compare_ts
int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b)
Compare two timestamps each in its own time base.
Definition: mathematics.c:147
AVUUID
uint8_t AVUUID[AV_UUID_LEN]
Definition: uuid.h:60
out
FILE * out
Definition: movenc.c:55
FFStream::first_dts
int64_t first_dts
Timestamp corresponding to the last dts sync point.
Definition: internal.h:348
AVCodecParameters
This struct describes the properties of an encoded stream.
Definition: codec_par.h:47
avformat_new_stream
AVStream * avformat_new_stream(AVFormatContext *s, const struct AVCodec *c)
Add a new stream to a media file.
OutputStream::fragment_index
int fragment_index
Definition: hdsenc.c:55
avio_context_free
void avio_context_free(AVIOContext **s)
Free the supplied IO context and everything associated with it.
Definition: aviobuf.c:126
AVFormatContext::protocol_blacklist
char * protocol_blacklist
',' separated list of disallowed protocols.
Definition: avformat.h:1809
AV_TIME_BASE_Q
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:264
int64_t
long long int64_t
Definition: coverity.c:34
ffurl_write
static int ffurl_write(URLContext *h, const uint8_t *buf, int size)
Write size bytes from buf to the resource accessed by h.
Definition: url.h:202
OutputStream::packets_written
atomic_uint_least64_t packets_written
Definition: ffmpeg.h:623
AVFormatContext::streams
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1368
deinit
static void deinit(AVFormatContext *s)
Definition: chromaprint.c:52
SmoothStreamingContext
Definition: smoothstreamingenc.c:67
avio_alloc_context
AVIOContext * avio_alloc_context(unsigned char *buffer, int buffer_size, int write_flag, void *opaque, int(*read_packet)(void *opaque, uint8_t *buf, int buf_size), int(*write_packet)(void *opaque, const uint8_t *buf, int buf_size), int64_t(*seek)(void *opaque, int64_t offset, int whence))
Allocate and initialize an AVIOContext for buffered I/O.
Definition: aviobuf.c:109
AVOption
AVOption.
Definition: opt.h:429
outfile
FILE * outfile
Definition: audiogen.c:96
Fragment::start_time
int64_t start_time
Definition: hdsenc.c:41
copy_moof
static int copy_moof(AVFormatContext *s, const char *infile, const char *outfile, int64_t size)
Definition: smoothstreamingenc.c:472
mathematics.h
AVDictionary
Definition: dict.c:34
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
SmoothStreamingContext::extra_window_size
int extra_window_size
Definition: smoothstreamingenc.c:70
OutputStream::nb_fragments
int nb_fragments
Definition: hdsenc.c:55
OutputStream::audio_tag
int audio_tag
Definition: smoothstreamingenc.c:62
SmoothStreamingContext::nb_fragments
int nb_fragments
Definition: smoothstreamingenc.c:76
os_support.h
AV_PKT_FLAG_KEY
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: packet.h:594
get_private_data
static void get_private_data(OutputStream *os)
Definition: smoothstreamingenc.c:139
FFOutputFormat::p
AVOutputFormat p
The public AVOutputFormat.
Definition: mux.h:65
Fragment
Definition: hdsenc.c:39
AVFormatContext::interrupt_callback
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition: avformat.h:1573
OutputStream::stream_type_tag
const char * stream_type_tag
Definition: smoothstreamingenc.c:55
ffstream
static av_always_inline FFStream * ffstream(AVStream *st)
Definition: internal.h:358
fail
#define fail()
Definition: checkasm.h:189
Fragment::file
char file[1024]
Definition: hdsenc.c:40
SmoothStreamingContext::has_audio
int has_audio
Definition: smoothstreamingenc.c:75
avio_tell
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:494
ff_rename
int ff_rename(const char *url_src, const char *url_dst, void *logctx)
Wrap ffurl_move() and log if error happens.
Definition: avio.c:861
OutputStream::tail_out
URLContext * tail_out
Definition: smoothstreamingenc.c:52
avio_rb32
unsigned int avio_rb32(AVIOContext *s)
Definition: aviobuf.c:761
pkt
AVPacket * pkt
Definition: movenc.c:60
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
SmoothStreamingContext::window_size
int window_size
Definition: smoothstreamingenc.c:69
duration
int64_t duration
Definition: movenc.c:65
ffurl_open_whitelist
int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options, const char *whitelist, const char *blacklist, URLContext *parent)
Create an URLContext for accessing to the resource indicated by url, and open it.
Definition: avio.c:362
OFFSET
#define OFFSET(x)
Definition: smoothstreamingenc.c:624
Fragment::start_pos
int64_t start_pos
Definition: smoothstreamingenc.c:43
s
#define s(width, name)
Definition: cbs_vp9.c:198
AV_CODEC_ID_WMAPRO
@ AV_CODEC_ID_WMAPRO
Definition: codec_id.h:483
bitrate
int64_t bitrate
Definition: av1_levels.c:47
ism_flush
static int ism_flush(AVFormatContext *s, int final)
Definition: smoothstreamingenc.c:499
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
AV_OPT_TYPE_INT64
@ AV_OPT_TYPE_INT64
Underlying C type is int64_t.
Definition: opt.h:263
ism_write_trailer
static int ism_write_trailer(AVFormatContext *s)
Definition: smoothstreamingenc.c:609
AVIO_FLAG_WRITE
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:618
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:230
ctx
AVFormatContext * ctx
Definition: movenc.c:49
av_rescale_q
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
ism_seek
static int64_t ism_seek(void *opaque, int64_t offset, int whence)
Definition: smoothstreamingenc.c:92
AV_CODEC_ID_H264
@ AV_CODEC_ID_H264
Definition: codec_id.h:79
avformat_write_header
av_warn_unused_result int avformat_write_header(AVFormatContext *s, AVDictionary **options)
Allocate the stream private data and write the stream header to an output media file.
Definition: mux.c:488
avio_flush
void avio_flush(AVIOContext *s)
Force flushing of buffered data.
Definition: aviobuf.c:223
AVFormatContext
Format I/O context.
Definition: avformat.h:1300
internal.h
opts
AVDictionary * opts
Definition: movenc.c:51
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:771
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:75
AVStream::time_base
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition: avformat.h:787
NULL
#define NULL
Definition: coverity.c:32
OutputStream::dirname
char dirname[1024]
Definition: smoothstreamingenc.c:63
write_trailer
static int write_trailer(AVFormatContext *s1)
Definition: v4l2enc.c:101
AVFormatContext::protocol_whitelist
char * protocol_whitelist
',' separated list of allowed protocols.
Definition: avformat.h:1802
ff_copy_whiteblacklists
int ff_copy_whiteblacklists(AVFormatContext *dst, const AVFormatContext *src)
Copies the whilelists from one context to the other.
Definition: avformat.c:912
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:237
avio_rb64
uint64_t avio_rb64(AVIOContext *s)
Definition: aviobuf.c:908
AVFormatContext::pb
AVIOContext * pb
I/O context.
Definition: avformat.h:1342
avc.h
FFOutputFormat
Definition: mux.h:61
av_write_frame
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file.
Definition: mux.c:1236
Fragment::duration
int64_t duration
Definition: hdsenc.c:41
index
int index
Definition: gxfenc.c:90
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
ism_free
static void ism_free(AVFormatContext *s)
Definition: smoothstreamingenc.c:162
AVCodecParameters::extradata_size
int extradata_size
Size of the extradata content in bytes.
Definition: codec_par.h:73
AV_CODEC_ID_AAC
@ AV_CODEC_ID_AAC
Definition: codec_id.h:448
avio_rl32
unsigned int avio_rl32(AVIOContext *s)
Definition: aviobuf.c:730
AVIOContext
Bytestream IO Context.
Definition: avio.h:160
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:94
avformat_alloc_context
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
Definition: options.c:162
FFStream
Definition: internal.h:132
start_time
static int64_t start_time
Definition: ffplay.c:326
uuid.h
Fragment::size
int64_t size
Definition: smoothstreamingenc.c:43
size
int size
Definition: twinvq_data.h:10344
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
AVFMT_NOFILE
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:468
ff_format_io_close
int ff_format_io_close(AVFormatContext *s, AVIOContext **pb)
Definition: avformat.c:958
AVStream::sample_aspect_ratio
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition: avformat.h:826
SmoothStreamingContext::min_frag_duration
int min_frag_duration
Definition: smoothstreamingenc.c:72
AVPacket::dts
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition: packet.h:538
avio_write
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:201
av_reallocp_array
int av_reallocp_array(void *ptr, size_t nmemb, size_t size)
Allocate, reallocate an array through a pointer to a pointer.
Definition: mem.c:225
offset
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Definition: writing_filters.txt:86
OutputStream::fourcc
const char * fourcc
Definition: smoothstreamingenc.c:59
AVPacket::flags
int flags
A combination of AV_PKT_FLAG values.
Definition: packet.h:545
av_dict_free
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition: dict.c:223
write_manifest
static int write_manifest(AVFormatContext *s, int final)
Definition: smoothstreamingenc.c:204
OutputStream::private_str
char * private_str
Definition: smoothstreamingenc.c:60
SmoothStreamingContext::lookahead_count
int lookahead_count
Definition: smoothstreamingenc.c:71
av_uuid_equal
static int av_uuid_equal(const AVUUID uu1, const AVUUID uu2)
Compares two UUIDs for equality.
Definition: uuid.h:119
URLContext
Definition: url.h:35
AVFMT_GLOBALHEADER
#define AVFMT_GLOBALHEADER
Format wants global header.
Definition: avformat.h:478
AVOutputFormat
Definition: avformat.h:509
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
AVERROR_MUXER_NOT_FOUND
#define AVERROR_MUXER_NOT_FOUND
Muxer not found.
Definition: error.h:62
AV_TIME_BASE
#define AV_TIME_BASE
Internal time base represented as integer.
Definition: avutil.h:254
AVCodecParameters::block_align
int block_align
Audio only.
Definition: codec_par.h:191
OutputStream::tail_pos
int64_t tail_pos
Definition: smoothstreamingenc.c:53
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
url.h
OutputStream::ctx
AVFormatContext * ctx
Definition: dashenc.c:107
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:256
AV_CODEC_ID_VC1
@ AV_CODEC_ID_VC1
Definition: codec_id.h:122
len
int len
Definition: vorbis_enc_data.h:426
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:264
write_packet
static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt)
Definition: ffmpeg_mux.c:209
ism_write_packet
static int ism_write_packet(AVFormatContext *s, AVPacket *pkt)
Definition: smoothstreamingenc.c:583
ffurl_closep
int ffurl_closep(URLContext **hh)
Close the resource accessed by the URLContext h, and free the memory used by it.
Definition: avio.c:588
tag
uint32_t tag
Definition: movenc.c:1879
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:748
avio_seek
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:231
AVClass::class_name
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:80
AVFormatContext::oformat
const struct AVOutputFormat * oformat
The output container format.
Definition: avformat.h:1319
SmoothStreamingContext::streams
OutputStream * streams
Definition: smoothstreamingenc.c:74
ism_class
static const AVClass ism_class
Definition: smoothstreamingenc.c:635
options
static const AVOption options[]
Definition: smoothstreamingenc.c:626
avformat.h
parse_fragment
static int parse_fragment(AVFormatContext *s, const char *filename, int64_t *start_ts, int64_t *duration, int64_t *moof_size, int64_t size)
Definition: smoothstreamingenc.c:394
OutputStream::fragments_size
int fragments_size
Definition: hdsenc.c:55
OutputStream::fragments
Fragment ** fragments
Definition: hdsenc.c:56
avio_printf
int avio_printf(AVIOContext *s, const char *fmt,...) av_printf_format(2
Writes a formatted string to the context.
OutputStream::out
URLContext * out
Definition: smoothstreamingenc.c:50
ff_avc_write_annexb_extradata
int ff_avc_write_annexb_extradata(const uint8_t *in, uint8_t **buf, int *size)
Definition: avc.c:144
OutputStream::iobuf
uint8_t iobuf[32768]
Definition: hdsenc.c:50
ism_write
static int ism_write(void *opaque, const uint8_t *buf, int buf_size)
Definition: smoothstreamingenc.c:79
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition: opt.h:259
ism_write_header
static int ism_write_header(AVFormatContext *s)
Definition: smoothstreamingenc.c:282
avformat_free_context
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition: avformat.c:149
avio_read
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:612
output_chunk_list
static void output_chunk_list(OutputStream *os, AVIOContext *out, int final, int skip, int window_size)
Definition: smoothstreamingenc.c:184
AVPacket::stream_index
int stream_index
Definition: packet.h:541
OutputStream::out
AVIOContext * out
Definition: dashenc.c:109
av_dict_set_int
int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags)
Convenience wrapper for av_dict_set() that converts the value to a string and stores it.
Definition: dict.c:167
AVIO_FLAG_READ
#define AVIO_FLAG_READ
read-only
Definition: avio.h:617
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
av_guess_format
const 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:79
mem.h
OutputStream::out2
URLContext * out2
Definition: smoothstreamingenc.c:51
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:55
AVPacket
This structure stores compressed data.
Definition: packet.h:516
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition: opt.h:327
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
av_dict_set
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition: dict.c:88
OutputStream::cur_pos
int64_t cur_pos
Definition: smoothstreamingenc.c:53
OutputStream
Definition: mux.c:53
av_strlcpy
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
Definition: avstring.c:85
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
MKTAG
#define MKTAG(a, b, c, d)
Definition: macros.h:55
OutputStream::packet_size
int packet_size
Definition: smoothstreamingenc.c:61
avstring.h
write_header
static void write_header(FFV1Context *f)
Definition: ffv1enc.c:348
snprintf
#define snprintf
Definition: snprintf.h:34
Fragment::n
int n
Definition: hdsenc.c:42
SmoothStreamingContext::has_video
int has_video
Definition: smoothstreamingenc.c:75
skip
static void BS_FUNC() skip(BSCTX *bc, unsigned int n)
Skip n bits in the buffer.
Definition: bitstream_template.h:375
Fragment::infofile
char infofile[1024]
Definition: smoothstreamingenc.c:45
ff_smoothstreaming_muxer
const FFOutputFormat ff_smoothstreaming_muxer
Definition: smoothstreamingenc.c:643
avcodec_parameters_copy
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
Copy the contents of src to dst.
Definition: codec_par.c:106
E
#define E
Definition: smoothstreamingenc.c:625
add_fragment
static int add_fragment(OutputStream *os, const char *file, const char *infofile, int64_t start_time, int64_t duration, int64_t start_pos, int64_t size)
Definition: smoothstreamingenc.c:444
mux.h
ff_write_chained
int ff_write_chained(AVFormatContext *dst, int dst_stream, AVPacket *pkt, AVFormatContext *src, int interleave)
Write a packet to another muxer than the one the user originally intended.
Definition: mux.c:1397