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/opt.h"
35 #include "libavutil/avstring.h"
36 #include "libavutil/mathematics.h"
37 #include "libavutil/uuid.h"
38 
39 typedef struct Fragment {
40  int64_t start_time, duration;
41  int n;
42  int64_t start_pos, size;
43  char file[1024];
44  char infofile[1024];
45 } Fragment;
46 
47 typedef struct OutputStream {
49  URLContext *out; // Current output stream where all output is written
50  URLContext *out2; // Auxiliary output stream where all output is also written
51  URLContext *tail_out; // The actual main output stream, if we're currently seeked back to write elsewhere
53  int packets_written;
54  const char *stream_type_tag;
57 
58  const char *fourcc;
59  char *private_str;
61  int audio_tag;
62  char dirname[1024];
63  uint8_t iobuf[32768];
64 } OutputStream;
65 
66 typedef struct SmoothStreamingContext {
67  const AVClass *class; /* Class for private options. */
77 
78 static int ism_write(void *opaque, uint8_t *buf, int buf_size)
79 {
80  OutputStream *os = opaque;
81  if (os->out)
82  ffurl_write(os->out, buf, buf_size);
83  if (os->out2)
84  ffurl_write(os->out2, buf, buf_size);
85  os->cur_pos += buf_size;
86  if (os->cur_pos >= os->tail_pos)
87  os->tail_pos = os->cur_pos;
88  return buf_size;
89 }
90 
91 static int64_t ism_seek(void *opaque, int64_t offset, int whence)
92 {
93  OutputStream *os = opaque;
94  int i;
95  if (whence != SEEK_SET)
96  return AVERROR(ENOSYS);
97  if (os->tail_out) {
98  ffurl_closep(&os->out);
99  ffurl_closep(&os->out2);
100  os->out = os->tail_out;
101  os->tail_out = NULL;
102  }
103  if (offset >= os->cur_start_pos) {
104  if (os->out)
105  ffurl_seek(os->out, offset - os->cur_start_pos, SEEK_SET);
106  os->cur_pos = offset;
107  return offset;
108  }
109  for (i = os->nb_fragments - 1; i >= 0; i--) {
110  Fragment *frag = os->fragments[i];
111  if (offset >= frag->start_pos && offset < frag->start_pos + frag->size) {
112  int ret;
114  os->tail_out = os->out;
115  av_dict_set(&opts, "truncate", "0", 0);
118  av_dict_free(&opts);
119  if (ret < 0) {
120  os->out = os->tail_out;
121  os->tail_out = NULL;
122  return ret;
123  }
124  av_dict_set(&opts, "truncate", "0", 0);
127  av_dict_free(&opts);
128  ffurl_seek(os->out, offset - frag->start_pos, SEEK_SET);
129  if (os->out2)
130  ffurl_seek(os->out2, offset - frag->start_pos, SEEK_SET);
131  os->cur_pos = offset;
132  return offset;
133  }
134  }
135  return AVERROR(EIO);
136 }
137 
139 {
140  AVCodecParameters *par = os->ctx->streams[0]->codecpar;
141  uint8_t *ptr = par->extradata;
142  int size = par->extradata_size;
143  int i;
144  if (par->codec_id == AV_CODEC_ID_H264) {
145  ff_avc_write_annexb_extradata(ptr, &ptr, &size);
146  if (!ptr)
147  ptr = par->extradata;
148  }
149  if (!ptr)
150  return;
151  os->private_str = av_mallocz(2*size + 1);
152  if (!os->private_str)
153  goto fail;
154  for (i = 0; i < size; i++)
155  snprintf(&os->private_str[2*i], 3, "%02x", ptr[i]);
156 fail:
157  if (ptr != par->extradata)
158  av_free(ptr);
159 }
160 
162 {
163  SmoothStreamingContext *c = s->priv_data;
164  int i, j;
165  if (!c->streams)
166  return;
167  for (i = 0; i < s->nb_streams; i++) {
168  OutputStream *os = &c->streams[i];
169  ffurl_closep(&os->out);
170  ffurl_closep(&os->out2);
171  ffurl_closep(&os->tail_out);
172  if (os->ctx && os->ctx->pb)
173  avio_context_free(&os->ctx->pb);
175  av_freep(&os->private_str);
176  for (j = 0; j < os->nb_fragments; j++)
177  av_freep(&os->fragments[j]);
178  av_freep(&os->fragments);
179  }
180  av_freep(&c->streams);
181 }
182 
183 static void output_chunk_list(OutputStream *os, AVIOContext *out, int final, int skip, int window_size)
184 {
185  int removed = 0, i, start = 0;
186  if (os->nb_fragments <= 0)
187  return;
188  if (os->fragments[0]->n > 0)
189  removed = 1;
190  if (final)
191  skip = 0;
192  if (window_size)
193  start = FFMAX(os->nb_fragments - skip - window_size, 0);
194  for (i = start; i < os->nb_fragments - skip; i++) {
195  Fragment *frag = os->fragments[i];
196  if (!final || removed)
197  avio_printf(out, "<c t=\"%"PRIu64"\" d=\"%"PRIu64"\" />\n", frag->start_time, frag->duration);
198  else
199  avio_printf(out, "<c n=\"%d\" d=\"%"PRIu64"\" />\n", frag->n, frag->duration);
200  }
201 }
202 
203 static int write_manifest(AVFormatContext *s, int final)
204 {
205  SmoothStreamingContext *c = s->priv_data;
206  AVIOContext *out;
207  char filename[1024], temp_filename[1024];
208  int ret, i, video_chunks = 0, audio_chunks = 0, video_streams = 0, audio_streams = 0;
209  int64_t duration = 0;
210 
211  snprintf(filename, sizeof(filename), "%s/Manifest", s->url);
212  snprintf(temp_filename, sizeof(temp_filename), "%s/Manifest.tmp", s->url);
213  ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL);
214  if (ret < 0) {
215  av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
216  return ret;
217  }
218  avio_printf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
219  for (i = 0; i < s->nb_streams; i++) {
220  OutputStream *os = &c->streams[i];
221  if (os->nb_fragments > 0) {
222  Fragment *last = os->fragments[os->nb_fragments - 1];
223  duration = last->start_time + last->duration;
224  }
225  if (s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
226  video_chunks = os->nb_fragments;
227  video_streams++;
228  } else {
229  audio_chunks = os->nb_fragments;
230  audio_streams++;
231  }
232  }
233  if (!final) {
234  duration = 0;
235  video_chunks = audio_chunks = 0;
236  }
237  if (c->window_size) {
238  video_chunks = FFMIN(video_chunks, c->window_size);
239  audio_chunks = FFMIN(audio_chunks, c->window_size);
240  }
241  avio_printf(out, "<SmoothStreamingMedia MajorVersion=\"2\" MinorVersion=\"0\" Duration=\"%"PRIu64"\"", duration);
242  if (!final)
243  avio_printf(out, " IsLive=\"true\" LookAheadFragmentCount=\"%d\" DVRWindowLength=\"0\"", c->lookahead_count);
244  avio_printf(out, ">\n");
245  if (c->has_video) {
246  int last = -1, index = 0;
247  avio_printf(out, "<StreamIndex Type=\"video\" QualityLevels=\"%d\" Chunks=\"%d\" Url=\"QualityLevels({bitrate})/Fragments(video={start time})\">\n", video_streams, video_chunks);
248  for (i = 0; i < s->nb_streams; i++) {
249  OutputStream *os = &c->streams[i];
250  if (s->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)
251  continue;
252  last = i;
253  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);
254  index++;
255  }
256  output_chunk_list(&c->streams[last], out, final, c->lookahead_count, c->window_size);
257  avio_printf(out, "</StreamIndex>\n");
258  }
259  if (c->has_audio) {
260  int last = -1, index = 0;
261  avio_printf(out, "<StreamIndex Type=\"audio\" QualityLevels=\"%d\" Chunks=\"%d\" Url=\"QualityLevels({bitrate})/Fragments(audio={start time})\">\n", audio_streams, audio_chunks);
262  for (i = 0; i < s->nb_streams; i++) {
263  OutputStream *os = &c->streams[i];
264  if (s->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
265  continue;
266  last = i;
267  avio_printf(out, "<QualityLevel Index=\"%d\" Bitrate=\"%"PRId64"\" FourCC=\"%s\" SamplingRate=\"%d\" Channels=\"%d\" BitsPerSample=\"16\" PacketSize=\"%d\" AudioTag=\"%d\" CodecPrivateData=\"%s\" />\n",
268  index, s->streams[i]->codecpar->bit_rate, os->fourcc, s->streams[i]->codecpar->sample_rate,
269  s->streams[i]->codecpar->ch_layout.nb_channels, os->packet_size, os->audio_tag, os->private_str);
270  index++;
271  }
272  output_chunk_list(&c->streams[last], out, final, c->lookahead_count, c->window_size);
273  avio_printf(out, "</StreamIndex>\n");
274  }
275  avio_printf(out, "</SmoothStreamingMedia>\n");
276  avio_flush(out);
278  return ff_rename(temp_filename, filename, s);
279 }
280 
282 {
283  SmoothStreamingContext *c = s->priv_data;
284  int ret = 0, i;
285  const AVOutputFormat *oformat;
286 
287  if (mkdir(s->url, 0777) == -1 && errno != EEXIST) {
288  av_log(s, AV_LOG_ERROR, "mkdir failed\n");
289  return AVERROR(errno);
290  }
291 
292  oformat = av_guess_format("ismv", NULL, NULL);
293  if (!oformat) {
295  }
296 
297  c->streams = av_calloc(s->nb_streams, sizeof(*c->streams));
298  if (!c->streams) {
299  return AVERROR(ENOMEM);
300  }
301 
302  for (i = 0; i < s->nb_streams; i++) {
303  OutputStream *os = &c->streams[i];
305  AVStream *st;
307 
308  if (!s->streams[i]->codecpar->bit_rate) {
309  av_log(s, AV_LOG_WARNING, "No bit rate set for stream %d\n", i);
310  // create a tmp name for the directory of fragments
311  snprintf(os->dirname, sizeof(os->dirname), "%s/QualityLevels(Tmp_%d)", s->url, i);
312  } else {
313  snprintf(os->dirname, sizeof(os->dirname), "%s/QualityLevels(%"PRId64")", s->url, s->streams[i]->codecpar->bit_rate);
314  }
315 
316  if (mkdir(os->dirname, 0777) == -1 && errno != EEXIST) {
317  av_log(s, AV_LOG_ERROR, "mkdir failed\n");
318  return AVERROR(errno);
319  }
320 
321  os->ctx = ctx = avformat_alloc_context();
322  if (!ctx) {
323  return AVERROR(ENOMEM);
324  }
325  if ((ret = ff_copy_whiteblacklists(ctx, s)) < 0)
326  return ret;
327  ctx->oformat = oformat;
328  ctx->interrupt_callback = s->interrupt_callback;
329 
330  if (!(st = avformat_new_stream(ctx, NULL))) {
331  return AVERROR(ENOMEM);
332  }
333  avcodec_parameters_copy(st->codecpar, s->streams[i]->codecpar);
334  st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio;
335  st->time_base = s->streams[i]->time_base;
336 
337  ctx->pb = avio_alloc_context(os->iobuf, sizeof(os->iobuf), 1, os, NULL, ism_write, ism_seek);
338  if (!ctx->pb) {
339  return AVERROR(ENOMEM);
340  }
341 
342  av_dict_set_int(&opts, "ism_lookahead", c->lookahead_count, 0);
343  av_dict_set(&opts, "movflags", "frag_custom", 0);
345  av_dict_free(&opts);
346  if (ret < 0) {
347  return ret;
348  }
349  avio_flush(ctx->pb);
350  s->streams[i]->time_base = st->time_base;
351  if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
352  c->has_video = 1;
353  os->stream_type_tag = "video";
354  if (st->codecpar->codec_id == AV_CODEC_ID_H264) {
355  os->fourcc = "H264";
356  } else if (st->codecpar->codec_id == AV_CODEC_ID_VC1) {
357  os->fourcc = "WVC1";
358  } else {
359  av_log(s, AV_LOG_ERROR, "Unsupported video codec\n");
360  return AVERROR(EINVAL);
361  }
362  } else {
363  c->has_audio = 1;
364  os->stream_type_tag = "audio";
365  if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
366  os->fourcc = "AACL";
367  os->audio_tag = 0xff;
368  } else if (st->codecpar->codec_id == AV_CODEC_ID_WMAPRO) {
369  os->fourcc = "WMAP";
370  os->audio_tag = 0x0162;
371  } else {
372  av_log(s, AV_LOG_ERROR, "Unsupported audio codec\n");
373  return AVERROR(EINVAL);
374  }
375  os->packet_size = st->codecpar->block_align ? st->codecpar->block_align : 4;
376  }
377  get_private_data(os);
378  }
379 
380  if (!c->has_video && c->min_frag_duration <= 0) {
381  av_log(s, AV_LOG_WARNING, "no video stream and no min frag duration set\n");
382  return AVERROR(EINVAL);
383  }
384  ret = write_manifest(s, 0);
385  if (ret < 0)
386  return ret;
387 
388  return 0;
389 }
390 
391 static int parse_fragment(AVFormatContext *s, const char *filename, int64_t *start_ts, int64_t *duration, int64_t *moof_size, int64_t size)
392 {
393  AVIOContext *in;
394  int ret;
395  uint32_t len;
396  if ((ret = s->io_open(s, &in, filename, AVIO_FLAG_READ, NULL)) < 0)
397  return ret;
398  ret = AVERROR(EIO);
399  *moof_size = avio_rb32(in);
400  if (*moof_size < 8 || *moof_size > size)
401  goto fail;
402  if (avio_rl32(in) != MKTAG('m','o','o','f'))
403  goto fail;
404  len = avio_rb32(in);
405  if (len > *moof_size)
406  goto fail;
407  if (avio_rl32(in) != MKTAG('m','f','h','d'))
408  goto fail;
409  avio_seek(in, len - 8, SEEK_CUR);
410  avio_rb32(in); /* traf size */
411  if (avio_rl32(in) != MKTAG('t','r','a','f'))
412  goto fail;
413  while (avio_tell(in) < *moof_size) {
414  uint32_t len = avio_rb32(in);
415  uint32_t tag = avio_rl32(in);
416  int64_t end = avio_tell(in) + len - 8;
417  if (len < 8 || len >= *moof_size)
418  goto fail;
419  if (tag == MKTAG('u','u','i','d')) {
420  static const AVUUID tfxd = {
421  0x6d, 0x1d, 0x9b, 0x05, 0x42, 0xd5, 0x44, 0xe6,
422  0x80, 0xe2, 0x14, 0x1d, 0xaf, 0xf7, 0x57, 0xb2
423  };
424  AVUUID uuid;
425  avio_read(in, uuid, 16);
426  if (av_uuid_equal(uuid, tfxd) && len >= 8 + 16 + 4 + 16) {
427  avio_seek(in, 4, SEEK_CUR);
428  *start_ts = avio_rb64(in);
429  *duration = avio_rb64(in);
430  ret = 0;
431  break;
432  }
433  }
434  avio_seek(in, end, SEEK_SET);
435  }
436 fail:
437  ff_format_io_close(s, &in);
438  return ret;
439 }
440 
441 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)
442 {
443  int err;
444  Fragment *frag;
445  if (os->nb_fragments >= os->fragments_size) {
446  os->fragments_size = (os->fragments_size + 1) * 2;
447  if ((err = av_reallocp_array(&os->fragments, sizeof(*os->fragments),
448  os->fragments_size)) < 0) {
449  os->fragments_size = 0;
450  os->nb_fragments = 0;
451  return err;
452  }
453  }
454  frag = av_mallocz(sizeof(*frag));
455  if (!frag)
456  return AVERROR(ENOMEM);
457  av_strlcpy(frag->file, file, sizeof(frag->file));
458  av_strlcpy(frag->infofile, infofile, sizeof(frag->infofile));
459  frag->start_time = start_time;
460  frag->duration = duration;
461  frag->start_pos = start_pos;
462  frag->size = size;
463  frag->n = os->fragment_index;
464  os->fragments[os->nb_fragments++] = frag;
465  os->fragment_index++;
466  return 0;
467 }
468 
469 static int copy_moof(AVFormatContext *s, const char* infile, const char *outfile, int64_t size)
470 {
471  AVIOContext *in, *out;
472  int ret = 0;
473  if ((ret = s->io_open(s, &in, infile, AVIO_FLAG_READ, NULL)) < 0)
474  return ret;
475  if ((ret = s->io_open(s, &out, outfile, AVIO_FLAG_WRITE, NULL)) < 0) {
476  ff_format_io_close(s, &in);
477  return ret;
478  }
479  while (size > 0) {
480  uint8_t buf[8192];
481  int n = FFMIN(size, sizeof(buf));
482  n = avio_read(in, buf, n);
483  if (n <= 0) {
484  ret = AVERROR(EIO);
485  break;
486  }
487  avio_write(out, buf, n);
488  size -= n;
489  }
490  avio_flush(out);
492  ff_format_io_close(s, &in);
493  return ret;
494 }
495 
496 static int ism_flush(AVFormatContext *s, int final)
497 {
498  SmoothStreamingContext *c = s->priv_data;
499  int i, ret = 0;
500 
501  for (i = 0; i < s->nb_streams; i++) {
502  OutputStream *os = &c->streams[i];
503  char filename[1024], target_filename[1024], header_filename[1024], curr_dirname[1024];
504  int64_t size;
505  int64_t start_ts, duration, moof_size;
506  if (!os->packets_written)
507  continue;
508 
509  snprintf(filename, sizeof(filename), "%s/temp", os->dirname);
510  ret = ffurl_open_whitelist(&os->out, filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL, s->protocol_whitelist, s->protocol_blacklist, NULL);
511  if (ret < 0)
512  break;
513  os->cur_start_pos = os->tail_pos;
514  av_write_frame(os->ctx, NULL);
515  avio_flush(os->ctx->pb);
516  os->packets_written = 0;
517  if (!os->out || os->tail_out)
518  return AVERROR(EIO);
519 
520  ffurl_closep(&os->out);
521  size = os->tail_pos - os->cur_start_pos;
522  if ((ret = parse_fragment(s, filename, &start_ts, &duration, &moof_size, size)) < 0)
523  break;
524 
525  if (!s->streams[i]->codecpar->bit_rate) {
526  int64_t bitrate = (int64_t) size * 8 * AV_TIME_BASE / av_rescale_q(duration, s->streams[i]->time_base, AV_TIME_BASE_Q);
527  if (!bitrate) {
528  av_log(s, AV_LOG_ERROR, "calculating bitrate got zero.\n");
529  ret = AVERROR(EINVAL);
530  return ret;
531  }
532 
533  av_log(s, AV_LOG_DEBUG, "calculated bitrate: %"PRId64"\n", bitrate);
534  s->streams[i]->codecpar->bit_rate = bitrate;
535  memcpy(curr_dirname, os->dirname, sizeof(os->dirname));
536  snprintf(os->dirname, sizeof(os->dirname), "%s/QualityLevels(%"PRId64")", s->url, s->streams[i]->codecpar->bit_rate);
537  snprintf(filename, sizeof(filename), "%s/temp", os->dirname);
538 
539  // rename the tmp folder back to the correct name since we now have the bitrate
540  if ((ret = ff_rename((const char*)curr_dirname, os->dirname, s)) < 0)
541  return ret;
542  }
543 
544  snprintf(header_filename, sizeof(header_filename), "%s/FragmentInfo(%s=%"PRIu64")", os->dirname, os->stream_type_tag, start_ts);
545  snprintf(target_filename, sizeof(target_filename), "%s/Fragments(%s=%"PRIu64")", os->dirname, os->stream_type_tag, start_ts);
546  copy_moof(s, filename, header_filename, moof_size);
547  ret = ff_rename(filename, target_filename, s);
548  if (ret < 0)
549  break;
550  add_fragment(os, target_filename, header_filename, start_ts, duration,
551  os->cur_start_pos, size);
552  }
553 
554  if (c->window_size || (final && c->remove_at_exit)) {
555  for (i = 0; i < s->nb_streams; i++) {
556  OutputStream *os = &c->streams[i];
557  int j;
558  int remove = os->nb_fragments - c->window_size - c->extra_window_size - c->lookahead_count;
559  if (final && c->remove_at_exit)
560  remove = os->nb_fragments;
561  if (remove > 0) {
562  for (j = 0; j < remove; j++) {
563  unlink(os->fragments[j]->file);
564  unlink(os->fragments[j]->infofile);
565  av_freep(&os->fragments[j]);
566  }
567  os->nb_fragments -= remove;
568  memmove(os->fragments, os->fragments + remove, os->nb_fragments * sizeof(*os->fragments));
569  }
570  if (final && c->remove_at_exit)
571  rmdir(os->dirname);
572  }
573  }
574 
575  if (ret >= 0)
576  ret = write_manifest(s, final);
577  return ret;
578 }
579 
581 {
582  SmoothStreamingContext *c = s->priv_data;
583  AVStream *st = s->streams[pkt->stream_index];
584  FFStream *const sti = ffstream(st);
585  OutputStream *os = &c->streams[pkt->stream_index];
586  int64_t end_dts = (c->nb_fragments + 1) * (int64_t) c->min_frag_duration;
587  int ret;
588 
589  if (sti->first_dts == AV_NOPTS_VALUE)
590  sti->first_dts = pkt->dts;
591 
592  if ((!c->has_video || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) &&
593  av_compare_ts(pkt->dts - sti->first_dts, st->time_base,
594  end_dts, AV_TIME_BASE_Q) >= 0 &&
596 
597  if ((ret = ism_flush(s, 0)) < 0)
598  return ret;
599  c->nb_fragments++;
600  }
601 
602  os->packets_written++;
603  return ff_write_chained(os->ctx, 0, pkt, s, 0);
604 }
605 
607 {
608  SmoothStreamingContext *c = s->priv_data;
609  ism_flush(s, 1);
610 
611  if (c->remove_at_exit) {
612  char filename[1024];
613  snprintf(filename, sizeof(filename), "%s/Manifest", s->url);
614  unlink(filename);
615  rmdir(s->url);
616  }
617 
618  return 0;
619 }
620 
621 #define OFFSET(x) offsetof(SmoothStreamingContext, x)
622 #define E AV_OPT_FLAG_ENCODING_PARAM
623 static const AVOption options[] = {
624  { "window_size", "number of fragments kept in the manifest", OFFSET(window_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, E },
625  { "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 },
626  { "lookahead_count", "number of lookahead fragments", OFFSET(lookahead_count), AV_OPT_TYPE_INT, { .i64 = 2 }, 0, INT_MAX, E },
627  { "min_frag_duration", "minimum fragment duration (in microseconds)", OFFSET(min_frag_duration), AV_OPT_TYPE_INT64, { .i64 = 5000000 }, 0, INT_MAX, E },
628  { "remove_at_exit", "remove all fragments when finished", OFFSET(remove_at_exit), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
629  { NULL },
630 };
631 
632 static const AVClass ism_class = {
633  .class_name = "smooth streaming muxer",
634  .item_name = av_default_item_name,
635  .option = options,
636  .version = LIBAVUTIL_VERSION_INT,
637 };
638 
639 
641  .name = "smoothstreaming",
642  .long_name = NULL_IF_CONFIG_SMALL("Smooth Streaming Muxer"),
643  .priv_data_size = sizeof(SmoothStreamingContext),
644  .audio_codec = AV_CODEC_ID_AAC,
645  .video_codec = AV_CODEC_ID_H264,
650  .deinit = ism_free,
651  .priv_class = &ism_class,
652 };
SmoothStreamingContext::remove_at_exit
int remove_at_exit
Definition: smoothstreamingenc.c:72
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
AVCodecParameters::extradata
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: codec_par.h:75
OutputStream::cur_start_pos
int64_t cur_start_pos
Definition: smoothstreamingenc.c:52
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
avformat_new_stream
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: options.c:237
AVCodecParameters::codec_type
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:57
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:54
FFStream::first_dts
int64_t first_dts
Timestamp corresponding to the last dts sync point.
Definition: internal.h:403
AVCodecParameters
This struct describes the properties of an encoded stream.
Definition: codec_par.h:53
ffurl_seek
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: avio.c:428
OutputStream::fragment_index
int fragment_index
Definition: hdsenc.c:54
avio_context_free
void avio_context_free(AVIOContext **s)
Free the supplied IO context and everything associated with it.
Definition: aviobuf.c:152
AVFormatContext::protocol_blacklist
char * protocol_blacklist
',' separated list of disallowed protocols.
Definition: avformat.h:1786
AV_TIME_BASE_Q
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:260
OutputStream::packets_written
atomic_uint_least64_t packets_written
Definition: ffmpeg.h:585
AVFormatContext::streams
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1281
deinit
static void deinit(AVFormatContext *s)
Definition: chromaprint.c:49
SmoothStreamingContext
Definition: smoothstreamingenc.c:66
AVOption
AVOption.
Definition: opt.h:251
outfile
FILE * outfile
Definition: audiogen.c:96
Fragment::start_time
int64_t start_time
Definition: hdsenc.c:40
copy_moof
static int copy_moof(AVFormatContext *s, const char *infile, const char *outfile, int64_t size)
Definition: smoothstreamingenc.c:469
mathematics.h
AVDictionary
Definition: dict.c:30
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
SmoothStreamingContext::extra_window_size
int extra_window_size
Definition: smoothstreamingenc.c:69
OutputStream::nb_fragments
int nb_fragments
Definition: hdsenc.c:54
OutputStream::audio_tag
int audio_tag
Definition: smoothstreamingenc.c:61
SmoothStreamingContext::nb_fragments
int nb_fragments
Definition: smoothstreamingenc.c:75
os_support.h
AV_PKT_FLAG_KEY
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: packet.h:429
get_private_data
static void get_private_data(OutputStream *os)
Definition: smoothstreamingenc.c:138
Fragment
Definition: hdsenc.c:38
AVFormatContext::interrupt_callback
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition: avformat.h:1480
OutputStream::stream_type_tag
const char * stream_type_tag
Definition: smoothstreamingenc.c:54
ffstream
static av_always_inline FFStream * ffstream(AVStream *st)
Definition: internal.h:407
fail
#define fail()
Definition: checkasm.h:131
Fragment::file
char file[1024]
Definition: hdsenc.c:39
SmoothStreamingContext::has_audio
int has_audio
Definition: smoothstreamingenc.c:74
avio_tell
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:505
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:665
OutputStream::tail_out
URLContext * tail_out
Definition: smoothstreamingenc.c:51
avio_rb32
unsigned int avio_rb32(AVIOContext *s)
Definition: aviobuf.c:790
pkt
AVPacket * pkt
Definition: movenc.c:59
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
SmoothStreamingContext::window_size
int window_size
Definition: smoothstreamingenc.c:68
duration
int64_t duration
Definition: movenc.c:64
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:306
OFFSET
#define OFFSET(x)
Definition: smoothstreamingenc.c:621
Fragment::start_pos
int64_t start_pos
Definition: smoothstreamingenc.c:42
s
#define s(width, name)
Definition: cbs_vp9.c:256
AV_CODEC_ID_WMAPRO
@ AV_CODEC_ID_WMAPRO
Definition: codec_id.h:466
ism_flush
static int ism_flush(AVFormatContext *s, int final)
Definition: smoothstreamingenc.c:496
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
AV_OPT_TYPE_INT64
@ AV_OPT_TYPE_INT64
Definition: opt.h:226
ism_write_trailer
static int ism_write_trailer(AVFormatContext *s)
Definition: smoothstreamingenc.c:606
AVIO_FLAG_WRITE
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:629
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:201
ctx
AVFormatContext * ctx
Definition: movenc.c:48
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
ff_smoothstreaming_muxer
const AVOutputFormat ff_smoothstreaming_muxer
Definition: smoothstreamingenc.c:640
ism_seek
static int64_t ism_seek(void *opaque, int64_t offset, int whence)
Definition: smoothstreamingenc.c:91
AV_CODEC_ID_H264
@ AV_CODEC_ID_H264
Definition: codec_id.h:77
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:449
ism_write
static int ism_write(void *opaque, uint8_t *buf, int buf_size)
Definition: smoothstreamingenc.c:78
avio_flush
void avio_flush(AVIOContext *s)
Force flushing of buffered data.
Definition: aviobuf.c:252
AVFormatContext
Format I/O context.
Definition: avformat.h:1213
internal.h
opts
AVDictionary * opts
Definition: movenc.c:50
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1108
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
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:978
NULL
#define NULL
Definition: coverity.c:32
OutputStream::dirname
char dirname[1024]
Definition: smoothstreamingenc.c:62
write_trailer
static int write_trailer(AVFormatContext *s1)
Definition: v4l2enc.c:100
AVFormatContext::protocol_whitelist
char * protocol_whitelist
',' separated list of allowed protocols.
Definition: avformat.h:1751
ff_copy_whiteblacklists
int ff_copy_whiteblacklists(AVFormatContext *dst, const AVFormatContext *src)
Copies the whilelists from one context to the other.
Definition: avformat.c:807
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:937
AVFormatContext::pb
AVIOContext * pb
I/O context.
Definition: avformat.h:1255
avc.h
av_write_frame
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file.
Definition: mux.c:1188
Fragment::duration
int64_t duration
Definition: hdsenc.c:40
index
int index
Definition: gxfenc.c:89
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
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:1350
ism_free
static void ism_free(AVFormatContext *s)
Definition: smoothstreamingenc.c:161
AVCodecParameters::extradata_size
int extradata_size
Size of the extradata content in bytes.
Definition: codec_par.h:79
AV_CODEC_ID_AAC
@ AV_CODEC_ID_AAC
Definition: codec_id.h:431
avio_rl32
unsigned int avio_rl32(AVIOContext *s)
Definition: aviobuf.c:759
AVIOContext
Bytestream IO Context.
Definition: avio.h:162
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:117
avformat_alloc_context
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
Definition: options.c:164
FFStream
Definition: internal.h:197
start_time
static int64_t start_time
Definition: ffplay.c:331
uuid.h
Fragment::size
int64_t size
Definition: smoothstreamingenc.c:42
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:470
ff_format_io_close
int ff_format_io_close(AVFormatContext *s, AVIOContext **pb)
Definition: avformat.c:845
AVStream::sample_aspect_ratio
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition: avformat.h:1017
SmoothStreamingContext::min_frag_duration
int min_frag_duration
Definition: smoothstreamingenc.c:71
AVPacket::dts
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition: packet.h:373
avio_write
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:232
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:233
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:58
AVPacket::flags
int flags
A combination of AV_PKT_FLAG values.
Definition: packet.h:380
av_dict_free
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition: dict.c:203
bitrate
int64_t bitrate
Definition: h264_levels.c:131
write_manifest
static int write_manifest(AVFormatContext *s, int final)
Definition: smoothstreamingenc.c:203
OutputStream::private_str
char * private_str
Definition: smoothstreamingenc.c:59
SmoothStreamingContext::lookahead_count
int lookahead_count
Definition: smoothstreamingenc.c:70
avcodec_parameters_copy
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
Copy the contents of src to dst.
Definition: codec_par.c:74
av_uuid_equal
static int av_uuid_equal(const AVUUID uu1, const AVUUID uu2)
Compares two UUIDs for equality.
Definition: uuid.h:120
URLContext
Definition: url.h:37
AVFMT_GLOBALHEADER
#define AVFMT_GLOBALHEADER
Format wants global header.
Definition: avformat.h:480
AVOutputFormat
Definition: avformat.h:509
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
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:184
OutputStream::tail_pos
int64_t tail_pos
Definition: smoothstreamingenc.c:52
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
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, 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:135
url.h
OutputStream::ctx
AVFormatContext * ctx
Definition: dashenc.c:103
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:264
AV_CODEC_ID_VC1
@ AV_CODEC_ID_VC1
Definition: codec_id.h:120
len
int len
Definition: vorbis_enc_data.h:426
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:272
ism_write_packet
static int ism_write_packet(AVFormatContext *s, AVPacket *pkt)
Definition: smoothstreamingenc.c:580
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:438
tag
uint32_t tag
Definition: movenc.c:1646
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:948
avio_seek
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:260
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:71
AVFormatContext::oformat
const struct AVOutputFormat * oformat
The output container format.
Definition: avformat.h:1232
SmoothStreamingContext::streams
OutputStream * streams
Definition: smoothstreamingenc.c:73
ism_class
static const AVClass ism_class
Definition: smoothstreamingenc.c:632
options
static const AVOption options[]
Definition: smoothstreamingenc.c:623
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:391
OutputStream::fragments_size
int fragments_size
Definition: hdsenc.c:54
OutputStream::fragments
Fragment ** fragments
Definition: hdsenc.c:55
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:49
ff_avc_write_annexb_extradata
int ff_avc_write_annexb_extradata(const uint8_t *in, uint8_t **buf, int *size)
Definition: avc.c:255
OutputStream::iobuf
uint8_t iobuf[32768]
Definition: hdsenc.c:49
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:225
ism_write_header
static int ism_write_header(AVFormatContext *s)
Definition: smoothstreamingenc.c:281
avformat_free_context
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition: avformat.c:95
avio_read
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:641
ffurl_write
int ffurl_write(URLContext *h, const unsigned char *buf, int size)
Write size bytes from buf to the resource accessed by h.
Definition: avio.c:415
output_chunk_list
static void output_chunk_list(OutputStream *os, AVIOContext *out, int final, int skip, int window_size)
Definition: smoothstreamingenc.c:183
AVPacket::stream_index
int stream_index
Definition: packet.h:376
OutputStream::out
AVIOContext * out
Definition: dashenc.c:105
av_dict_set_int
int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags)
Convenience wrapper for av_dict_set that converts the value to a string and stores it.
Definition: dict.c:147
AVIO_FLAG_READ
#define AVIO_FLAG_READ
read-only
Definition: avio.h:628
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:53
OutputStream::out2
URLContext * out2
Definition: smoothstreamingenc.c:50
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:61
AVPacket
This structure stores compressed data.
Definition: packet.h:351
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:244
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:70
OutputStream::cur_pos
int64_t cur_pos
Definition: smoothstreamingenc.c:52
OutputStream
Definition: muxing.c:54
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
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:86
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:60
avstring.h
write_header
static void write_header(FFV1Context *f)
Definition: ffv1enc.c:346
write_packet
static int write_packet(OutputFile *of, OutputStream *ost, AVPacket *pkt)
Definition: ffmpeg_mux.c:90
snprintf
#define snprintf
Definition: snprintf.h:34
Fragment::n
int n
Definition: hdsenc.c:41
SmoothStreamingContext::has_video
int has_video
Definition: smoothstreamingenc.c:74
Fragment::infofile
char infofile[1024]
Definition: smoothstreamingenc.c:44
E
#define E
Definition: smoothstreamingenc.c:622
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:441
mux.h