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 
35 #include "libavutil/mem.h"
36 #include "libavutil/opt.h"
37 #include "libavutil/avstring.h"
38 #include "libavutil/mathematics.h"
39 #include "libavutil/uuid.h"
40 
41 typedef struct Fragment {
43  int n;
45  char file[1024];
46  char infofile[1024];
47 } Fragment;
48 
49 typedef struct OutputStream {
51  URLContext *out; // Current output stream where all output is written
52  URLContext *out2; // Auxiliary output stream where all output is also written
53  URLContext *tail_out; // The actual main output stream, if we're currently seeked back to write elsewhere
55  int packets_written;
56  const char *stream_type_tag;
59 
60  const char *fourcc;
61  char *private_str;
63  int audio_tag;
64  char dirname[1024];
65  uint8_t iobuf[32768];
66 } OutputStream;
67 
68 typedef struct SmoothStreamingContext {
69  const AVClass *class; /* Class for private options. */
79 
80 static int ism_write(void *opaque, const uint8_t *buf, int buf_size)
81 {
82  OutputStream *os = opaque;
83  if (os->out)
84  ffurl_write(os->out, buf, buf_size);
85  if (os->out2)
86  ffurl_write(os->out2, buf, buf_size);
87  os->cur_pos += buf_size;
88  if (os->cur_pos >= os->tail_pos)
89  os->tail_pos = os->cur_pos;
90  return buf_size;
91 }
92 
93 static int64_t ism_seek(void *opaque, int64_t offset, int whence)
94 {
95  OutputStream *os = opaque;
96  int i;
97  if (whence != SEEK_SET)
98  return AVERROR(ENOSYS);
99  if (os->tail_out) {
100  ffurl_closep(&os->out);
101  ffurl_closep(&os->out2);
102  os->out = os->tail_out;
103  os->tail_out = NULL;
104  }
105  if (offset >= os->cur_start_pos) {
106  if (os->out)
107  ffurl_seek(os->out, offset - os->cur_start_pos, SEEK_SET);
108  os->cur_pos = offset;
109  return offset;
110  }
111  for (i = os->nb_fragments - 1; i >= 0; i--) {
112  Fragment *frag = os->fragments[i];
113  if (offset >= frag->start_pos && offset < frag->start_pos + frag->size) {
114  int ret;
116  os->tail_out = os->out;
117  av_dict_set(&opts, "truncate", "0", 0);
120  av_dict_free(&opts);
121  if (ret < 0) {
122  os->out = os->tail_out;
123  os->tail_out = NULL;
124  return ret;
125  }
126  av_dict_set(&opts, "truncate", "0", 0);
129  av_dict_free(&opts);
130  ffurl_seek(os->out, offset - frag->start_pos, SEEK_SET);
131  if (os->out2)
132  ffurl_seek(os->out2, offset - frag->start_pos, SEEK_SET);
133  os->cur_pos = offset;
134  return offset;
135  }
136  }
137  return AVERROR(EIO);
138 }
139 
141 {
142  AVCodecParameters *par = os->ctx->streams[0]->codecpar;
143  uint8_t *ptr = par->extradata;
144  int size = par->extradata_size;
145  int i;
146  if (par->codec_id == AV_CODEC_ID_H264) {
147  ff_avc_write_annexb_extradata(ptr, &ptr, &size);
148  if (!ptr)
149  ptr = par->extradata;
150  }
151  if (!ptr)
152  return;
153  os->private_str = av_mallocz(2*size + 1);
154  if (!os->private_str)
155  goto fail;
156  for (i = 0; i < size; i++)
157  snprintf(&os->private_str[2*i], 3, "%02x", ptr[i]);
158 fail:
159  if (ptr != par->extradata)
160  av_free(ptr);
161 }
162 
164 {
165  SmoothStreamingContext *c = s->priv_data;
166  int i, j;
167  if (!c->streams)
168  return;
169  for (i = 0; i < s->nb_streams; i++) {
170  OutputStream *os = &c->streams[i];
171  ffurl_closep(&os->out);
172  ffurl_closep(&os->out2);
173  ffurl_closep(&os->tail_out);
174  if (os->ctx && os->ctx->pb)
175  avio_context_free(&os->ctx->pb);
177  av_freep(&os->private_str);
178  for (j = 0; j < os->nb_fragments; j++)
179  av_freep(&os->fragments[j]);
180  av_freep(&os->fragments);
181  }
182  av_freep(&c->streams);
183 }
184 
185 static void output_chunk_list(OutputStream *os, AVIOContext *out, int final, int skip, int window_size)
186 {
187  int removed = 0, i, start = 0;
188  if (os->nb_fragments <= 0)
189  return;
190  if (os->fragments[0]->n > 0)
191  removed = 1;
192  if (final)
193  skip = 0;
194  if (window_size)
195  start = FFMAX(os->nb_fragments - skip - window_size, 0);
196  for (i = start; i < os->nb_fragments - skip; i++) {
197  Fragment *frag = os->fragments[i];
198  if (!final || removed)
199  avio_printf(out, "<c t=\"%"PRIu64"\" d=\"%"PRIu64"\" />\n", frag->start_time, frag->duration);
200  else
201  avio_printf(out, "<c n=\"%d\" d=\"%"PRIu64"\" />\n", frag->n, frag->duration);
202  }
203 }
204 
205 static int write_manifest(AVFormatContext *s, int final)
206 {
207  SmoothStreamingContext *c = s->priv_data;
208  AVIOContext *out;
209  char filename[1024], temp_filename[1024];
210  int ret, i, video_chunks = 0, audio_chunks = 0, video_streams = 0, audio_streams = 0;
211  int64_t duration = 0;
212 
213  snprintf(filename, sizeof(filename), "%s/Manifest", s->url);
214  snprintf(temp_filename, sizeof(temp_filename), "%s/Manifest.tmp", s->url);
215  ret = s->io_open(s, &out, temp_filename, AVIO_FLAG_WRITE, NULL);
216  if (ret < 0) {
217  av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
218  return ret;
219  }
220  avio_printf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
221  for (i = 0; i < s->nb_streams; i++) {
222  OutputStream *os = &c->streams[i];
223  if (os->nb_fragments > 0) {
224  Fragment *last = os->fragments[os->nb_fragments - 1];
225  duration = last->start_time + last->duration;
226  }
227  if (s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
228  video_chunks = os->nb_fragments;
229  video_streams++;
230  } else {
231  audio_chunks = os->nb_fragments;
232  audio_streams++;
233  }
234  }
235  if (!final) {
236  duration = 0;
237  video_chunks = audio_chunks = 0;
238  }
239  if (c->window_size) {
240  video_chunks = FFMIN(video_chunks, c->window_size);
241  audio_chunks = FFMIN(audio_chunks, c->window_size);
242  }
243  avio_printf(out, "<SmoothStreamingMedia MajorVersion=\"2\" MinorVersion=\"0\" Duration=\"%"PRIu64"\"", duration);
244  if (!final)
245  avio_printf(out, " IsLive=\"true\" LookAheadFragmentCount=\"%d\" DVRWindowLength=\"0\"", c->lookahead_count);
246  avio_printf(out, ">\n");
247  if (c->has_video) {
248  int last = -1, index = 0;
249  avio_printf(out, "<StreamIndex Type=\"video\" QualityLevels=\"%d\" Chunks=\"%d\" Url=\"QualityLevels({bitrate})/Fragments(video={start time})\">\n", video_streams, video_chunks);
250  for (i = 0; i < s->nb_streams; i++) {
251  OutputStream *os = &c->streams[i];
252  if (s->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)
253  continue;
254  last = i;
255  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);
256  index++;
257  }
258  output_chunk_list(&c->streams[last], out, final, c->lookahead_count, c->window_size);
259  avio_printf(out, "</StreamIndex>\n");
260  }
261  if (c->has_audio) {
262  int last = -1, index = 0;
263  avio_printf(out, "<StreamIndex Type=\"audio\" QualityLevels=\"%d\" Chunks=\"%d\" Url=\"QualityLevels({bitrate})/Fragments(audio={start time})\">\n", audio_streams, audio_chunks);
264  for (i = 0; i < s->nb_streams; i++) {
265  OutputStream *os = &c->streams[i];
266  if (s->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
267  continue;
268  last = i;
269  avio_printf(out, "<QualityLevel Index=\"%d\" Bitrate=\"%"PRId64"\" FourCC=\"%s\" SamplingRate=\"%d\" Channels=\"%d\" BitsPerSample=\"16\" PacketSize=\"%d\" AudioTag=\"%d\" CodecPrivateData=\"%s\" />\n",
270  index, s->streams[i]->codecpar->bit_rate, os->fourcc, s->streams[i]->codecpar->sample_rate,
271  s->streams[i]->codecpar->ch_layout.nb_channels, os->packet_size, os->audio_tag, os->private_str);
272  index++;
273  }
274  output_chunk_list(&c->streams[last], out, final, c->lookahead_count, c->window_size);
275  avio_printf(out, "</StreamIndex>\n");
276  }
277  avio_printf(out, "</SmoothStreamingMedia>\n");
278  avio_flush(out);
280  return ff_rename(temp_filename, filename, s);
281 }
282 
284 {
285  SmoothStreamingContext *c = s->priv_data;
286  int ret = 0, i;
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 
294  c->streams = av_calloc(s->nb_streams, sizeof(*c->streams));
295  if (!c->streams) {
296  return AVERROR(ENOMEM);
297  }
298 
299  for (i = 0; i < s->nb_streams; i++) {
300  OutputStream *os = &c->streams[i];
302  AVStream *st;
304 
305  if (!s->streams[i]->codecpar->bit_rate) {
306  av_log(s, AV_LOG_WARNING, "No bit rate set for stream %d\n", i);
307  // create a tmp name for the directory of fragments
308  snprintf(os->dirname, sizeof(os->dirname), "%s/QualityLevels(Tmp_%d)", s->url, i);
309  } else {
310  snprintf(os->dirname, sizeof(os->dirname), "%s/QualityLevels(%"PRId64")", s->url, s->streams[i]->codecpar->bit_rate);
311  }
312 
313  if (mkdir(os->dirname, 0777) == -1 && errno != EEXIST) {
314  av_log(s, AV_LOG_ERROR, "mkdir failed\n");
315  return AVERROR(errno);
316  }
317 
318  os->ctx = ctx = avformat_alloc_context();
319  if (!ctx) {
320  return AVERROR(ENOMEM);
321  }
322  if ((ret = ff_copy_whiteblacklists(ctx, s)) < 0)
323  return ret;
326  ctx->interrupt_callback = s->interrupt_callback;
327 
328  if (!(st = avformat_new_stream(ctx, NULL))) {
329  return AVERROR(ENOMEM);
330  }
331  if ((ret = avcodec_parameters_copy(st->codecpar, s->streams[i]->codecpar)) < 0) {
332  return ret;
333  }
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  .p.name = "smoothstreaming",
642  .p.long_name = NULL_IF_CONFIG_SMALL("Smooth Streaming Muxer"),
643  .p.audio_codec = AV_CODEC_ID_AAC,
644  .p.video_codec = AV_CODEC_ID_H264,
645  .p.flags = AVFMT_GLOBALHEADER | AVFMT_NOFILE,
646  .p.priv_class = &ism_class,
647  .priv_data_size = sizeof(SmoothStreamingContext),
651  .deinit = ism_free,
652 };
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:74
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:216
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:54
AVOutputFormat::name
const char * name
Definition: avformat.h:506
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
static FILE * out
Definition: movenc.c:55
FFStream::first_dts
int64_t first_dts
Timestamp corresponding to the last dts sync point.
Definition: internal.h:352
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:56
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:1770
AV_TIME_BASE_Q
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:263
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:688
AVFormatContext::streams
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1332
deinit
static void deinit(AVFormatContext *s)
Definition: chromaprint.c:53
SmoothStreamingContext
Definition: smoothstreamingenc.c:68
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:42
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:32
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
SmoothStreamingContext::extra_window_size
int extra_window_size
Definition: smoothstreamingenc.c:71
OutputStream::nb_fragments
int nb_fragments
Definition: hdsenc.c:56
OutputStream::audio_tag
int audio_tag
Definition: smoothstreamingenc.c:63
SmoothStreamingContext::nb_fragments
int nb_fragments
Definition: smoothstreamingenc.c:77
os_support.h
AV_PKT_FLAG_KEY
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: packet.h:643
get_private_data
static void get_private_data(OutputStream *os)
Definition: smoothstreamingenc.c:140
FFOutputFormat::p
AVOutputFormat p
The public AVOutputFormat.
Definition: mux.h:65
Fragment
Definition: hdsenc.c:40
AVFormatContext::interrupt_callback
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition: avformat.h:1534
OutputStream::stream_type_tag
const char * stream_type_tag
Definition: smoothstreamingenc.c:56
ffstream
static av_always_inline FFStream * ffstream(AVStream *st)
Definition: internal.h:362
fail
#define fail()
Definition: checkasm.h:218
Fragment::file
char file[1024]
Definition: hdsenc.c:41
SmoothStreamingContext::has_audio
int has_audio
Definition: smoothstreamingenc.c:76
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:862
OutputStream::tail_out
URLContext * tail_out
Definition: smoothstreamingenc.c:53
avio_rb32
unsigned int avio_rb32(AVIOContext *s)
Definition: aviobuf.c:764
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
SmoothStreamingContext::window_size
int window_size
Definition: smoothstreamingenc.c:70
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:363
OFFSET
#define OFFSET(x)
Definition: smoothstreamingenc.c:621
attributes_internal.h
Fragment::start_pos
int64_t start_pos
Definition: smoothstreamingenc.c:44
s
#define s(width, name)
Definition: cbs_vp9.c:198
AV_CODEC_ID_WMAPRO
@ AV_CODEC_ID_WMAPRO
Definition: codec_id.h:497
bitrate
int64_t bitrate
Definition: av1_levels.c:47
ism_flush
static int ism_flush(AVFormatContext *s, int final)
Definition: smoothstreamingenc.c:496
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:201
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:606
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:231
ctx
static 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:93
av_mallocz
#define av_mallocz(s)
Definition: tableprint_vlc.h:31
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:467
EXTERN
#define EXTERN
Definition: attributes_internal.h:34
avio_flush
void avio_flush(AVIOContext *s)
Force flushing of buffered data.
Definition: aviobuf.c:228
AVFormatContext
Format I/O context.
Definition: avformat.h:1264
internal.h
opts
static AVDictionary * opts
Definition: movenc.c:51
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:767
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:76
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:783
NULL
#define NULL
Definition: coverity.c:32
OutputStream::dirname
char dirname[1024]
Definition: smoothstreamingenc.c:64
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:1763
ff_copy_whiteblacklists
int ff_copy_whiteblacklists(AVFormatContext *dst, const AVFormatContext *src)
Copies the whilelists from one context to the other.
Definition: avformat.c:825
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:242
avio_rb64
uint64_t avio_rb64(AVIOContext *s)
Definition: aviobuf.c:911
AVFormatContext::pb
AVIOContext * pb
I/O context.
Definition: avformat.h:1306
avc.h
options
Definition: swscale.c:43
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:1176
Fragment::duration
int64_t duration
Definition: hdsenc.c:42
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:163
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:462
avio_rl32
unsigned int avio_rl32(AVIOContext *s)
Definition: aviobuf.c:733
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:163
FFStream
Definition: internal.h:128
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
start_time
static int64_t start_time
Definition: ffplay.c:328
uuid.h
Fragment::size
int64_t size
Definition: smoothstreamingenc.c:44
size
int size
Definition: twinvq_data.h:10344
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:247
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:871
AVStream::sample_aspect_ratio
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition: avformat.h:822
SmoothStreamingContext::min_frag_duration
int min_frag_duration
Definition: smoothstreamingenc.c:73
AVPacket::dts
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition: packet.h:587
avio_write
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:206
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:60
AVPacket::flags
int flags
A combination of AV_PKT_FLAG values.
Definition: packet.h:594
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:233
write_manifest
static int write_manifest(AVFormatContext *s, int final)
Definition: smoothstreamingenc.c:205
OutputStream::private_str
char * private_str
Definition: smoothstreamingenc.c:61
SmoothStreamingContext::lookahead_count
int lookahead_count
Definition: smoothstreamingenc.c:72
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:477
AV_TIME_BASE
#define AV_TIME_BASE
Internal time base represented as integer.
Definition: avutil.h:253
AVCodecParameters::block_align
int block_align
Audio only.
Definition: codec_par.h:191
OutputStream::tail_pos
int64_t tail_pos
Definition: smoothstreamingenc.c:54
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
url.h
OutputStream::ctx
AVFormatContext * ctx
Definition: dashenc.c:103
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: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:589
tag
uint32_t tag
Definition: movenc.c:2032
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:744
avio_seek
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:236
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:81
AVFormatContext::oformat
const struct AVOutputFormat * oformat
The output container format.
Definition: avformat.h:1283
SmoothStreamingContext::streams
OutputStream * streams
Definition: smoothstreamingenc.c:75
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:56
OutputStream::fragments
Fragment ** fragments
Definition: hdsenc.c:57
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:51
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:51
ism_write
static int ism_write(void *opaque, const uint8_t *buf, int buf_size)
Definition: smoothstreamingenc.c:80
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:283
avformat_free_context
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition: avformat.c:143
avio_read
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:615
output_chunk_list
static void output_chunk_list(OutputStream *os, AVIOContext *out, int final, int skip, int window_size)
Definition: smoothstreamingenc.c:185
AVPacket::stream_index
int stream_index
Definition: packet.h:590
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:177
AVIO_FLAG_READ
#define AVIO_FLAG_READ
read-only
Definition: avio.h:617
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:200
mem.h
OutputStream::out2
URLContext * out2
Definition: smoothstreamingenc.c:52
ff_ismv_muxer
const FFOutputFormat ff_ismv_muxer
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
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:565
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:35
av_dict_set
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition: dict.c:86
OutputStream::cur_pos
int64_t cur_pos
Definition: smoothstreamingenc.c:54
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:62
pkt
static AVPacket * pkt
Definition: demux_decode.c:55
avstring.h
write_header
static void write_header(FFV1Context *f)
Definition: ffv1enc.c:384
snprintf
#define snprintf
Definition: snprintf.h:34
Fragment::n
int n
Definition: hdsenc.c:43
SmoothStreamingContext::has_video
int has_video
Definition: smoothstreamingenc.c:76
skip
static void BS_FUNC() skip(BSCTX *bc, unsigned int n)
Skip n bits in the buffer.
Definition: bitstream_template.h:383
Fragment::infofile
char infofile[1024]
Definition: smoothstreamingenc.c:46
duration
static int64_t duration
Definition: ffplay.c:329
ff_smoothstreaming_muxer
const FFOutputFormat ff_smoothstreaming_muxer
Definition: smoothstreamingenc.c:640
avcodec_parameters_copy
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
Copy the contents of src to dst.
Definition: codec_par.c:107
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
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:1337