FFmpeg
movenc.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Martin Storsjo
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include "config.h"
22 
23 #include "libavutil/intreadwrite.h"
24 #include "libavutil/mathematics.h"
25 #include "libavutil/md5.h"
26 
27 #include "libavformat/avformat.h"
28 
29 #if HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
32 
33 #if !HAVE_GETOPT
34 #include "compat/getopt.c"
35 #endif
36 
37 #define HASH_SIZE 16
38 
39 static const uint8_t h264_extradata[] = {
40  0x01, 0x4d, 0x40, 0x1e, 0xff, 0xe1, 0x00, 0x02, 0x67, 0x4d, 0x01, 0x00, 0x02, 0x68, 0xef
41 };
42 static const uint8_t aac_extradata[] = {
43  0x12, 0x10
44 };
45 
46 
47 static const char *format = "mp4";
49 uint8_t iobuf[32768];
51 
53 const char *cur_name;
54 FILE* out;
56 struct AVMD5* md5;
57 uint8_t hash[HASH_SIZE];
58 
62 
63 int bframes;
64 int64_t duration;
66 int frames;
68 int64_t next_p_pts;
76 
78 
80 
81 
82 static void count_warnings(void *avcl, int level, const char *fmt, va_list vl)
83 {
84  if (level == AV_LOG_WARNING)
85  num_warnings++;
86 }
87 
88 static void init_count_warnings(void)
89 {
91  num_warnings = 0;
92 }
93 
94 static void reset_count_warnings(void)
95 {
97 }
98 
99 static int io_write(void *opaque, uint8_t *buf, int size)
100 {
101  out_size += size;
102  av_md5_update(md5, buf, size);
103  if (out)
104  fwrite(buf, 1, size, out);
105  return size;
106 }
107 
108 static int io_write_data_type(void *opaque, uint8_t *buf, int size,
109  enum AVIODataMarkerType type, int64_t time)
110 {
111  char timebuf[30], content[5] = { 0 };
112  const char *str;
113  switch (type) {
114  case AVIO_DATA_MARKER_HEADER: str = "header"; break;
115  case AVIO_DATA_MARKER_SYNC_POINT: str = "sync"; break;
116  case AVIO_DATA_MARKER_BOUNDARY_POINT: str = "boundary"; break;
117  case AVIO_DATA_MARKER_UNKNOWN: str = "unknown"; break;
118  case AVIO_DATA_MARKER_TRAILER: str = "trailer"; break;
119  default: str = "unknown"; break;
120  }
121  if (time == AV_NOPTS_VALUE)
122  snprintf(timebuf, sizeof(timebuf), "nopts");
123  else
124  snprintf(timebuf, sizeof(timebuf), "%"PRId64, time);
125  // There can be multiple header/trailer callbacks, only log the box type
126  // for header at out_size == 0
129  (type != AVIO_DATA_MARKER_HEADER || out_size == 0) &&
130  size >= 8)
131  memcpy(content, &buf[4], 4);
132  else
133  snprintf(content, sizeof(content), "-");
134  printf("write_data len %d, time %s, type %s atom %s\n", size, timebuf, str, content);
135  return io_write(opaque, buf, size);
136 }
137 
138 static void init_out(const char *name)
139 {
140  char buf[100];
141  cur_name = name;
142  snprintf(buf, sizeof(buf), "%s.%s", cur_name, format);
143 
144  av_md5_init(md5);
145  if (write_file) {
146  out = fopen(buf, "wb");
147  if (!out)
148  perror(buf);
149  }
150  out_size = 0;
151 }
152 
153 static void close_out(void)
154 {
155  int i;
157  for (i = 0; i < HASH_SIZE; i++)
158  printf("%02x", hash[i]);
159  printf(" %d %s\n", out_size, cur_name);
160  if (out)
161  fclose(out);
162  out = NULL;
163 }
164 
165 static void check_func(int value, int line, const char *msg, ...)
166 {
167  if (!value) {
168  va_list ap;
169  va_start(ap, msg);
170  printf("%d: ", line);
171  vprintf(msg, ap);
172  printf("\n");
173  check_faults++;
174  va_end(ap);
175  }
176 }
177 #define check(value, ...) check_func(value, __LINE__, __VA_ARGS__)
178 
179 static void init_fps(int bf, int audio_preroll, int fps)
180 {
181  AVStream *st;
182  int iobuf_size = force_iobuf_size ? force_iobuf_size : sizeof(iobuf);
184  if (!ctx)
185  exit(1);
187  if (!ctx->oformat)
188  exit(1);
189  ctx->pb = avio_alloc_context(iobuf, iobuf_size, 1, NULL, NULL, io_write, NULL);
190  if (!ctx->pb)
191  exit(1);
194 
196  if (!st)
197  exit(1);
200  st->codecpar->width = 640;
201  st->codecpar->height = 480;
202  st->time_base.num = 1;
203  st->time_base.den = 30;
204  st->codecpar->extradata_size = sizeof(h264_extradata);
206  if (!st->codecpar->extradata)
207  exit(1);
208  memcpy(st->codecpar->extradata, h264_extradata, sizeof(h264_extradata));
209  video_st = st;
210 
212  if (!st)
213  exit(1);
216  st->codecpar->sample_rate = 44100;
217  st->codecpar->channels = 2;
218  st->time_base.num = 1;
219  st->time_base.den = 44100;
220  st->codecpar->extradata_size = sizeof(aac_extradata);
222  if (!st->codecpar->extradata)
223  exit(1);
224  memcpy(st->codecpar->extradata, aac_extradata, sizeof(aac_extradata));
225  audio_st = st;
226 
227  if (avformat_write_header(ctx, &opts) < 0)
228  exit(1);
229  av_dict_free(&opts);
230 
231  frames = 0;
232  gop_size = 30;
233  duration = video_st->time_base.den / fps;
235  if (audio_preroll)
236  audio_preroll = 2048LL * audio_st->time_base.den / audio_st->codecpar->sample_rate;
237 
238  bframes = bf;
239  video_dts = bframes ? -duration : 0;
240  audio_dts = -audio_preroll;
241 }
242 
243 static void init(int bf, int audio_preroll)
244 {
245  init_fps(bf, audio_preroll, 30);
246 }
247 
248 static void mux_frames(int n, int c)
249 {
250  int end_frames = frames + n;
251  while (1) {
252  uint8_t pktdata[8] = { 0 };
254 
256  pkt->dts = pkt->pts = audio_dts;
257  pkt->stream_index = 1;
260  } else {
261  if (frames == end_frames)
262  break;
263  pkt->dts = video_dts;
264  pkt->stream_index = 0;
265  pkt->duration = duration;
266  if ((frames % gop_size) == 0) {
269  pkt->pts = pkt->dts + duration;
270  video_dts = pkt->pts;
271  } else {
274  pkt->pts = pkt->dts;
276  } else {
278  if (((frames + 1) % gop_size) == 0) {
279  pkt->pts = pkt->dts + duration;
280  video_dts = pkt->pts;
281  } else {
282  next_p_pts = pkt->pts = pkt->dts + 2 * duration;
283  video_dts += duration;
284  }
285  }
286  }
287  if (!bframes)
288  pkt->pts = pkt->dts;
289  if (fake_pkt_duration)
291  frames++;
292  }
293 
294  if (clear_duration)
295  pkt->duration = 0;
296  AV_WB32(pktdata + 4, pkt->pts);
297  pkt->data = pktdata;
298  pkt->size = 8;
299  if (skip_write)
300  continue;
301  if (skip_write_audio && pkt->stream_index == 1)
302  continue;
303 
304  if (c) {
305  pkt->pts += (1LL<<32);
306  pkt->dts += (1LL<<32);
307  }
308 
309  if (do_interleave)
311  else
313  }
314 }
315 
316 static void mux_gops(int n)
317 {
318  mux_frames(gop_size * n, 0);
319 }
320 
321 static void skip_gops(int n)
322 {
323  skip_write = 1;
324  mux_gops(n);
325  skip_write = 0;
326 }
327 
328 static void signal_init_ts(void)
329 {
331 
332  pkt->stream_index = 0;
333  pkt->dts = video_dts;
334  pkt->pts = 0;
336 
337  pkt->stream_index = 1;
338  pkt->dts = pkt->pts = audio_dts;
340 }
341 
342 static void finish(void)
343 {
347  ctx = NULL;
348 }
349 
350 static void help(void)
351 {
352  printf("movenc-test [-w]\n"
353  "-w write output into files\n");
354 }
355 
356 int main(int argc, char **argv)
357 {
358  int c;
359  uint8_t header[HASH_SIZE];
360  uint8_t content[HASH_SIZE];
361  int empty_moov_pos;
362  int prev_pos;
363 
364  for (;;) {
365  c = getopt(argc, argv, "wh");
366  if (c == -1)
367  break;
368  switch (c) {
369  case 'w':
370  write_file = 1;
371  break;
372  default:
373  case 'h':
374  help();
375  return 0;
376  }
377  }
378 
379  md5 = av_md5_alloc();
380  if (!md5)
381  return 1;
382  pkt = av_packet_alloc();
383  if (!pkt) {
384  av_free(md5);
385  return 1;
386  }
387 
388  // Write a fragmented file with an initial moov that actually contains some
389  // samples. One moov+mdat with 1 second of data and one moof+mdat with 1
390  // second of data.
391  init_out("non-empty-moov");
392  av_dict_set(&opts, "movflags", "frag_keyframe", 0);
393  init(0, 0);
394  mux_gops(2);
395  finish();
396  close_out();
397 
398  // Write a similar file, but with B-frames and audio preroll, handled
399  // via an edit list.
400  init_out("non-empty-moov-elst");
401  av_dict_set(&opts, "movflags", "frag_keyframe", 0);
402  av_dict_set(&opts, "use_editlist", "1", 0);
403  init(1, 1);
404  mux_gops(2);
405  finish();
406  close_out();
407 
408  // Use B-frames but no audio-preroll, but without an edit list.
409  // Due to avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO, the dts
410  // of the first audio packet is > 0, but it is set to zero since edit
411  // lists aren't used, increasing the duration of the first packet instead.
412  init_out("non-empty-moov-no-elst");
413  av_dict_set(&opts, "movflags", "frag_keyframe", 0);
414  av_dict_set(&opts, "use_editlist", "0", 0);
415  init(1, 0);
416  mux_gops(2);
417  finish();
418  close_out();
419 
420  format = "ismv";
421  // Write an ISMV, with B-frames and audio preroll.
422  init_out("ismv");
423  av_dict_set(&opts, "movflags", "frag_keyframe", 0);
424  init(1, 1);
425  mux_gops(2);
426  finish();
427  close_out();
428  format = "mp4";
429 
430  // An initial moov that doesn't contain any samples, followed by two
431  // moof+mdat pairs.
432  init_out("empty-moov");
433  av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0);
434  av_dict_set(&opts, "use_editlist", "0", 0);
435  init(0, 0);
436  mux_gops(2);
437  finish();
438  close_out();
439  memcpy(content, hash, HASH_SIZE);
440 
441  // Similar to the previous one, but with input that doesn't start at
442  // pts/dts 0. avoid_negative_ts behaves in the same way as
443  // in non-empty-moov-no-elst above.
444  init_out("empty-moov-no-elst");
445  av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0);
446  init(1, 0);
447  mux_gops(2);
448  finish();
449  close_out();
450 
451  // Same as the previous one, but disable avoid_negative_ts (which
452  // would require using an edit list, but with empty_moov, one can't
453  // write a sensible edit list, when the start timestamps aren't known).
454  // This should trigger a warning - we check that the warning is produced.
456  init_out("empty-moov-no-elst-no-adjust");
457  av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0);
458  av_dict_set(&opts, "avoid_negative_ts", "0", 0);
459  init(1, 0);
460  mux_gops(2);
461  finish();
462  close_out();
463 
465  check(num_warnings > 0, "No warnings printed for unhandled start offset");
466 
467  // Verify that delay_moov produces the same as empty_moov for
468  // simple input
469  init_out("delay-moov");
470  av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov", 0);
471  av_dict_set(&opts, "use_editlist", "0", 0);
472  init(0, 0);
473  mux_gops(2);
474  finish();
475  close_out();
476  check(!memcmp(hash, content, HASH_SIZE), "delay_moov differs from empty_moov");
477 
478  // Test writing content that requires an edit list using delay_moov
479  init_out("delay-moov-elst");
480  av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov", 0);
481  init(1, 1);
482  mux_gops(2);
483  finish();
484  close_out();
485 
486  // Test writing a file with one track lacking packets, with delay_moov.
487  skip_write_audio = 1;
488  init_out("delay-moov-empty-track");
489  av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov", 0);
490  init(0, 0);
491  mux_gops(2);
492  // The automatic flushing shouldn't output anything, since we're still
493  // waiting for data for some tracks
494  check(out_size == 0, "delay_moov flushed prematurely");
495  // When closed (or manually flushed), all the written data should still
496  // be output.
497  finish();
498  close_out();
499  check(out_size > 0, "delay_moov didn't output anything");
500 
501  // Check that manually flushing still outputs things as expected. This
502  // produces two fragments, while the one above produces only one.
503  init_out("delay-moov-empty-track-flush");
504  av_dict_set(&opts, "movflags", "frag_custom+delay_moov", 0);
505  init(0, 0);
506  mux_gops(1);
507  av_write_frame(ctx, NULL); // Force writing the moov
508  check(out_size > 0, "No moov written");
510  mux_gops(1);
512  finish();
513  close_out();
514 
515  skip_write_audio = 0;
516 
517 
518 
519  // Verify that the header written by delay_moov when manually flushed
520  // is identical to the one by empty_moov.
521  init_out("empty-moov-header");
522  av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0);
523  av_dict_set(&opts, "use_editlist", "0", 0);
524  init(0, 0);
525  close_out();
526  memcpy(header, hash, HASH_SIZE);
527  init_out("empty-moov-content");
528  mux_gops(2);
529  // Written 2 seconds of content, with an automatic flush after 1 second.
530  check(out_size > 0, "No automatic flush?");
531  empty_moov_pos = prev_pos = out_size;
532  // Manually flush the second fragment
534  check(out_size > prev_pos, "No second fragment flushed?");
535  prev_pos = out_size;
536  // Check that an extra flush doesn't output any more data
538  check(out_size == prev_pos, "More data written?");
539  close_out();
540  memcpy(content, hash, HASH_SIZE);
541  // Ignore the trailer written here
542  finish();
543 
544  init_out("delay-moov-header");
545  av_dict_set(&opts, "movflags", "frag_custom+delay_moov", 0);
546  av_dict_set(&opts, "use_editlist", "0", 0);
547  init(0, 0);
548  check(out_size == 0, "Output written during init with delay_moov");
549  mux_gops(1); // Write 1 second of content
550  av_write_frame(ctx, NULL); // Force writing the moov
551  close_out();
552  check(!memcmp(hash, header, HASH_SIZE), "delay_moov header differs from empty_moov");
553  init_out("delay-moov-content");
554  av_write_frame(ctx, NULL); // Flush the first fragment
555  check(out_size == empty_moov_pos, "Manually flushed content differs from automatically flushed, %d vs %d", out_size, empty_moov_pos);
556  mux_gops(1); // Write the rest of the content
557  av_write_frame(ctx, NULL); // Flush the second fragment
558  close_out();
559  check(!memcmp(hash, content, HASH_SIZE), "delay_moov content differs from empty_moov");
560  finish();
561 
562 
563  // Verify that we can produce an identical second fragment without
564  // writing the first one. First write the reference fragments that
565  // we want to reproduce.
566  av_dict_set(&opts, "movflags", "frag_custom+empty_moov+dash", 0);
567  init(0, 0);
568  mux_gops(1);
569  av_write_frame(ctx, NULL); // Output the first fragment
570  init_out("empty-moov-second-frag");
571  mux_gops(1);
572  av_write_frame(ctx, NULL); // Output the second fragment
573  close_out();
574  memcpy(content, hash, HASH_SIZE);
575  finish();
576 
577  // Produce the same second fragment without actually writing the first
578  // one before.
579  av_dict_set(&opts, "movflags", "frag_custom+empty_moov+dash+frag_discont", 0);
580  av_dict_set(&opts, "fragment_index", "2", 0);
581  av_dict_set(&opts, "avoid_negative_ts", "0", 0);
582  av_dict_set(&opts, "use_editlist", "0", 0);
583  init(0, 0);
584  skip_gops(1);
585  init_out("empty-moov-second-frag-discont");
586  mux_gops(1);
587  av_write_frame(ctx, NULL); // Output the second fragment
588  close_out();
589  check(!memcmp(hash, content, HASH_SIZE), "discontinuously written fragment differs");
590  finish();
591 
592  // Produce the same thing by using delay_moov, which requires a slightly
593  // different call sequence.
594  av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash+frag_discont", 0);
595  av_dict_set(&opts, "fragment_index", "2", 0);
596  init(0, 0);
597  skip_gops(1);
598  mux_gops(1);
599  av_write_frame(ctx, NULL); // Output the moov
600  init_out("delay-moov-second-frag-discont");
601  av_write_frame(ctx, NULL); // Output the second fragment
602  close_out();
603  check(!memcmp(hash, content, HASH_SIZE), "discontinuously written fragment differs");
604  finish();
605 
606 
607  // Test discontinuously written fragments with B-frames (where the
608  // assumption of starting at pts=0 works) but not with audio preroll
609  // (which can't be guessed).
610  av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash", 0);
611  init(1, 0);
612  mux_gops(1);
613  init_out("delay-moov-elst-init");
614  av_write_frame(ctx, NULL); // Output the moov
615  close_out();
616  memcpy(header, hash, HASH_SIZE);
617  av_write_frame(ctx, NULL); // Output the first fragment
618  init_out("delay-moov-elst-second-frag");
619  mux_gops(1);
620  av_write_frame(ctx, NULL); // Output the second fragment
621  close_out();
622  memcpy(content, hash, HASH_SIZE);
623  finish();
624 
625  av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash+frag_discont", 0);
626  av_dict_set(&opts, "fragment_index", "2", 0);
627  init(1, 0);
628  skip_gops(1);
629  mux_gops(1); // Write the second fragment
630  init_out("delay-moov-elst-init-discont");
631  av_write_frame(ctx, NULL); // Output the moov
632  close_out();
633  check(!memcmp(hash, header, HASH_SIZE), "discontinuously written header differs");
634  init_out("delay-moov-elst-second-frag-discont");
635  av_write_frame(ctx, NULL); // Output the second fragment
636  close_out();
637  check(!memcmp(hash, content, HASH_SIZE), "discontinuously written fragment differs");
638  finish();
639 
640 
641  // Test discontinuously written fragments with B-frames and audio preroll,
642  // properly signaled.
643  av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash", 0);
644  init(1, 1);
645  mux_gops(1);
646  init_out("delay-moov-elst-signal-init");
647  av_write_frame(ctx, NULL); // Output the moov
648  close_out();
649  memcpy(header, hash, HASH_SIZE);
650  av_write_frame(ctx, NULL); // Output the first fragment
651  init_out("delay-moov-elst-signal-second-frag");
652  mux_gops(1);
653  av_write_frame(ctx, NULL); // Output the second fragment
654  close_out();
655  memcpy(content, hash, HASH_SIZE);
656  finish();
657 
658  av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash+frag_discont", 0);
659  av_dict_set(&opts, "fragment_index", "2", 0);
660  init(1, 1);
661  signal_init_ts();
662  skip_gops(1);
663  mux_gops(1); // Write the second fragment
664  init_out("delay-moov-elst-signal-init-discont");
665  av_write_frame(ctx, NULL); // Output the moov
666  close_out();
667  check(!memcmp(hash, header, HASH_SIZE), "discontinuously written header differs");
668  init_out("delay-moov-elst-signal-second-frag-discont");
669  av_write_frame(ctx, NULL); // Output the second fragment
670  close_out();
671  check(!memcmp(hash, content, HASH_SIZE), "discontinuously written fragment differs");
672  finish();
673 
674 
675  // Test muxing discontinuous fragments with very large (> (1<<31)) timestamps.
676  av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash+frag_discont", 0);
677  av_dict_set(&opts, "fragment_index", "2", 0);
678  init(1, 1);
679  signal_init_ts();
680  skip_gops(1);
681  mux_frames(gop_size, 1); // Write the second fragment
682  init_out("delay-moov-elst-signal-init-discont-largets");
683  av_write_frame(ctx, NULL); // Output the moov
684  close_out();
685  init_out("delay-moov-elst-signal-second-frag-discont-largets");
686  av_write_frame(ctx, NULL); // Output the second fragment
687  close_out();
688  finish();
689 
690  // Test VFR content, with sidx atoms (which declare the pts duration
691  // of a fragment, forcing overriding the start pts of the next one).
692  // Here, the fragment duration in pts is significantly different from
693  // the duration in dts. The video stream starts at dts=-10,pts=0, and
694  // the second fragment starts at dts=155,pts=156. The trun duration sum
695  // of the first fragment is 165, which also is written as
696  // baseMediaDecodeTime in the tfdt in the second fragment. The sidx for
697  // the first fragment says earliest_presentation_time = 0 and
698  // subsegment_duration = 156, which also matches the sidx in the second
699  // fragment. For the audio stream, the pts and dts durations also don't
700  // match - the input stream starts at pts=-2048, but that part is excluded
701  // by the edit list.
702  init_out("vfr");
703  av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov+dash", 0);
704  init_fps(1, 1, 3);
705  mux_frames(gop_size/2, 0);
706  duration /= 10;
707  mux_frames(gop_size/2, 0);
708  mux_gops(1);
709  finish();
710  close_out();
711 
712  // Test VFR content, with cleared duration fields. In these cases,
713  // the muxer must guess the duration of the last packet of each
714  // fragment. As long as the framerate doesn't vary (too much) at the
715  // fragment edge, it works just fine. Additionally, when automatically
716  // cutting fragments, the muxer already know the timestamps of the next
717  // packet for one stream (in most cases the video stream), avoiding
718  // having to use guesses for that one.
720  clear_duration = 1;
721  init_out("vfr-noduration");
722  av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov+dash", 0);
723  init_fps(1, 1, 3);
724  mux_frames(gop_size/2, 0);
725  duration /= 10;
726  mux_frames(gop_size/2, 0);
727  mux_gops(1);
728  finish();
729  close_out();
730  clear_duration = 0;
732  check(num_warnings > 0, "No warnings printed for filled in durations");
733 
734  // Test with an IO buffer size that is too small to hold a full fragment;
735  // this will cause write_data_type to be called with the type unknown.
736  force_iobuf_size = 1500;
737  init_out("large_frag");
738  av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov", 0);
739  init_fps(1, 1, 3);
740  mux_gops(2);
741  finish();
742  close_out();
743  force_iobuf_size = 0;
744 
745  // Test VFR content with bframes with interleaving.
746  // Here, using av_interleaved_write_frame allows the muxer to get the
747  // fragment end durations right. We always set the packet duration to
748  // the expected, but we simulate dropped frames at one point.
749  do_interleave = 1;
750  init_out("vfr-noduration-interleave");
751  av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov", 0);
752  av_dict_set(&opts, "frag_duration", "650000", 0);
753  init_fps(1, 1, 30);
754  mux_frames(gop_size/2, 0);
755  // Pretend that the packet duration is the normal, even if
756  // we actually skip a bunch of frames. (I.e., simulate that
757  // we don't know of the framedrop in advance.)
759  duration *= 10;
760  mux_frames(1, 0);
761  fake_pkt_duration = 0;
762  duration /= 10;
763  mux_frames(gop_size/2 - 1, 0);
764  mux_gops(1);
765  finish();
766  close_out();
767  clear_duration = 0;
768  do_interleave = 0;
769 
770  // Write a fragmented file with b-frames and audio preroll,
771  // with negative cts values, removing the edit list for the
772  // video track.
773  init_out("delay-moov-elst-neg-cts");
774  av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov+negative_cts_offsets", 0);
775  init(1, 1);
776  mux_gops(2);
777  finish();
778  close_out();
779 
780  // Write a fragmented file with b-frames without audio preroll,
781  // with negative cts values, avoiding any edit lists, allowing
782  // to use empty_moov instead of delay_moov.
783  init_out("empty-moov-neg-cts");
784  av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov+negative_cts_offsets", 0);
785  init(1, 0);
786  mux_gops(2);
787  finish();
788  close_out();
789 
790  av_free(md5);
792 
793  return check_faults > 0 ? 1 : 0;
794 }
aac_extradata
static const uint8_t aac_extradata[]
Definition: movenc.c:42
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:424
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
skip_write
int skip_write
Definition: movenc.c:70
AVCodecParameters::extradata
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: codec_par.h:74
name
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 default minimum maximum flags name is the option name
Definition: writing_filters.txt:88
level
uint8_t level
Definition: svq3.c:204
AVIO_DATA_MARKER_BOUNDARY_POINT
@ AVIO_DATA_MARKER_BOUNDARY_POINT
A point in the output bytestream where a demuxer can start parsing (for non self synchronizing bytest...
Definition: avio.h:128
cur_name
const char * cur_name
Definition: movenc.c:53
avformat_new_stream
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:768
AVCodecParameters::codec_type
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:56
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:146
out
FILE * out
Definition: movenc.c:54
h264_extradata
static const uint8_t h264_extradata[]
Definition: movenc.c:39
avio_context_free
void avio_context_free(AVIOContext **s)
Free the supplied IO context and everything associated with it.
Definition: aviobuf.c:152
AVPictureType
AVPictureType
Definition: avutil.h:272
audio_dts
int64_t audio_dts
Definition: movenc.c:61
out_size
int out_size
Definition: movenc.c:55
AVPacket::data
uint8_t * data
Definition: packet.h:373
num_warnings
int num_warnings
Definition: movenc.c:77
last_picture
enum AVPictureType last_picture
Definition: movenc.c:69
check_func
static void check_func(int value, int line, const char *msg,...)
Definition: movenc.c:165
AVPacket::duration
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: packet.h:391
bframes
int bframes
Definition: movenc.c:63
mathematics.h
AVDictionary
Definition: dict.c:30
AVIODataMarkerType
AVIODataMarkerType
Different data types that can be returned via the AVIO write_data_type callback.
Definition: avio.h:111
hash
uint8_t hash[HASH_SIZE]
Definition: movenc.c:57
AV_PKT_FLAG_KEY
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: packet.h:428
av_packet_free
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition: avpacket.c:75
video_dts
int64_t video_dts
Definition: movenc.c:61
AVCodecParameters::channels
int channels
Audio only.
Definition: codec_par.h:166
finish
static void finish(void)
Definition: movenc.c:342
fake_pkt_duration
int fake_pkt_duration
Definition: movenc.c:75
md5
struct AVMD5 * md5
Definition: movenc.c:56
type
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 type
Definition: writing_filters.txt:86
AVMD5
Definition: md5.c:40
AVRational::num
int num
Numerator.
Definition: rational.h:59
gop_size
int gop_size
Definition: movenc.c:67
pkt
AVPacket * pkt
Definition: movenc.c:59
mux_frames
static void mux_frames(int n, int c)
Definition: movenc.c:248
getopt
static int getopt(int argc, char *argv[], char *opts)
Definition: getopt.c:41
duration
int64_t duration
Definition: movenc.c:64
io_write_data_type
static int io_write_data_type(void *opaque, uint8_t *buf, int size, enum AVIODataMarkerType type, int64_t time)
Definition: movenc.c:108
intreadwrite.h
AVFormatContext::flags
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1318
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
AVCodecParameters::width
int width
Video only.
Definition: codec_par.h:126
reset_count_warnings
static void reset_count_warnings(void)
Definition: movenc.c:94
ctx
AVFormatContext * ctx
Definition: movenc.c:48
force_iobuf_size
int force_iobuf_size
Definition: movenc.c:73
mux_gops
static void mux_gops(int n)
Definition: movenc.c:316
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:472
iobuf
uint8_t iobuf[32768]
Definition: movenc.c:49
AVFormatContext
Format I/O context.
Definition: avformat.h:1200
opts
AVDictionary * opts
Definition: movenc.c:50
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1095
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:965
NULL
#define NULL
Definition: coverity.c:32
AVIO_DATA_MARKER_TRAILER
@ AVIO_DATA_MARKER_TRAILER
Trailer data, which doesn't contain actual content, but only for finalizing the output file.
Definition: avio.h:140
AV_PICTURE_TYPE_I
@ AV_PICTURE_TYPE_I
Intra.
Definition: avutil.h:274
AVFormatContext::pb
AVIOContext * pb
I/O context.
Definition: avformat.h:1242
av_write_frame
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file.
Definition: mux.c:1181
audio_st
AVStream * audio_st
Definition: movenc.c:60
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
AVCodecParameters::sample_rate
int sample_rate
Audio only.
Definition: codec_par.h:170
AVCodecParameters::extradata_size
int extradata_size
Size of the extradata content in bytes.
Definition: codec_par.h:78
AV_WB32
#define AV_WB32(p, v)
Definition: intreadwrite.h:419
AV_CODEC_ID_AAC
@ AV_CODEC_ID_AAC
Definition: codec_id.h:425
audio_duration
int64_t audio_duration
Definition: movenc.c:65
av_log_set_callback
void av_log_set_callback(void(*callback)(void *, int, const char *, va_list))
Set the logging callback.
Definition: log.c:455
AVPacket::size
int size
Definition: packet.h:374
avformat_alloc_context
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
Definition: options.c:154
AVIOContext::write_data_type
int(* write_data_type)(void *opaque, uint8_t *buf, int buf_size, enum AVIODataMarkerType type, int64_t time)
A callback that is used instead of write_packet.
Definition: avio.h:284
size
int size
Definition: twinvq_data.h:10344
video_st
AVStream * video_st
Definition: movenc.c:60
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
frames
int frames
Definition: movenc.c:66
printf
printf("static const uint8_t my_array[100] = {\n")
skip_write_audio
int skip_write_audio
Definition: movenc.c:71
init_out
static void init_out(const char *name)
Definition: movenc.c:138
AVIO_DATA_MARKER_SYNC_POINT
@ AVIO_DATA_MARKER_SYNC_POINT
A point in the output bytestream where a decoder can start decoding (i.e.
Definition: avio.h:122
header
static const uint8_t header[24]
Definition: sdr2.c:67
AVPacket::dts
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition: packet.h:372
next_p_pts
int64_t next_p_pts
Definition: movenc.c:68
check
#define check(value,...)
Definition: movenc.c:177
line
Definition: graph2dot.c:48
AVPacket::flags
int flags
A combination of AV_PKT_FLAG values.
Definition: packet.h:379
av_packet_alloc
AVPacket * av_packet_alloc(void)
Allocate an AVPacket and set its fields to default values.
Definition: avpacket.c:64
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
init_fps
static void init_fps(int bf, int audio_preroll, int fps)
Definition: movenc.c:179
HASH_SIZE
#define HASH_SIZE
Definition: movenc.c:37
write_file
int write_file
Definition: movenc.c:52
check_faults
int check_faults
Definition: movenc.c:79
init
static void init(int bf, int audio_preroll)
Definition: movenc.c:243
av_write_trailer
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
Definition: mux.c:1243
av_md5_init
void av_md5_init(AVMD5 *ctx)
Initialize MD5 hashing.
Definition: md5.c:141
skip_gops
static void skip_gops(int n)
Definition: movenc.c:321
help
static void help(void)
Definition: movenc.c:350
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:271
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:366
AVCodecParameters::height
int height
Definition: codec_par.h:127
md5.h
value
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 default value
Definition: writing_filters.txt:86
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
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:263
av_md5_final
void av_md5_final(AVMD5 *ctx, uint8_t *dst)
Finish hashing and output digest value.
Definition: md5.c:186
format
static const char * format
Definition: movenc.c:47
AVIO_DATA_MARKER_UNKNOWN
@ AVIO_DATA_MARKER_UNKNOWN
This is any, unlabelled data.
Definition: avio.h:135
AVFMT_FLAG_BITEXACT
#define AVFMT_FLAG_BITEXACT
When muxing, try to avoid writing any random/volatile data to the output.
Definition: avformat.h:1335
AVStream
Stream structure.
Definition: avformat.h:935
AVFormatContext::oformat
const struct AVOutputFormat * oformat
The output container format.
Definition: avformat.h:1219
main
int main(int argc, char **argv)
Definition: movenc.c:356
avformat.h
getopt.c
AV_INPUT_BUFFER_PADDING_SIZE
#define AV_INPUT_BUFFER_PADDING_SIZE
Definition: defs.h:40
close_out
static void close_out(void)
Definition: movenc.c:153
AV_PICTURE_TYPE_B
@ AV_PICTURE_TYPE_B
Bi-dir predicted.
Definition: avutil.h:276
av_md5_alloc
struct AVMD5 * av_md5_alloc(void)
Allocate an AVMD5 context.
Definition: md5.c:48
AVRational::den
int den
Denominator.
Definition: rational.h:60
AVIO_DATA_MARKER_HEADER
@ AVIO_DATA_MARKER_HEADER
Header data; this needs to be present for the stream to be decodeable.
Definition: avio.h:115
avformat_free_context
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition: utils.c:688
init_count_warnings
static void init_count_warnings(void)
Definition: movenc.c:88
clear_duration
int clear_duration
Definition: movenc.c:72
AVPacket::stream_index
int stream_index
Definition: packet.h:375
av_md5_update
void av_md5_update(AVMD5 *ctx, const uint8_t *src, size_t len)
Update hash value.
Definition: md5.c:151
AV_PICTURE_TYPE_P
@ AV_PICTURE_TYPE_P
Predicted.
Definition: avutil.h:275
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
av_log_default_callback
void av_log_default_callback(void *ptr, int level, const char *fmt, va_list vl)
Default logging callback.
Definition: log.c:346
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:51
io_write
static int io_write(void *opaque, uint8_t *buf, int size)
Definition: movenc.c:99
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:60
AVPacket
This structure stores compressed data.
Definition: packet.h:350
av_interleaved_write_frame
int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file ensuring correct interleaving.
Definition: mux.c:1228
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
signal_init_ts
static void signal_init_ts(void)
Definition: movenc.c:328
convert_header.str
string str
Definition: convert_header.py:20
do_interleave
int do_interleave
Definition: movenc.c:74
count_warnings
static void count_warnings(void *avcl, int level, const char *fmt, va_list vl)
Definition: movenc.c:82
snprintf
#define snprintf
Definition: snprintf.h:34