FFmpeg
qt-faststart.c
Go to the documentation of this file.
1 /*
2  * qt-faststart.c, v0.2
3  * by Mike Melanson (melanson@pcisys.net)
4  * This file is placed in the public domain. Use the program however you
5  * see fit.
6  *
7  * This utility rearranges a Quicktime file such that the moov atom
8  * is in front of the data, thus facilitating network streaming.
9  *
10  * To compile this program, start from the base directory from which you
11  * are building FFmpeg and type:
12  * make tools/qt-faststart
13  * The qt-faststart program will be built in the tools/ directory. If you
14  * do not build the program in this manner, correct results are not
15  * guaranteed, particularly on 64-bit platforms.
16  * Invoke the program with:
17  * qt-faststart <infile.mov> <outfile.mov>
18  *
19  * Notes: Quicktime files can come in many configurations of top-level
20  * atoms. This utility stipulates that the very last atom in the file needs
21  * to be a moov atom. When given such a file, this utility will rearrange
22  * the top-level atoms by shifting the moov atom from the back of the file
23  * to the front, and patch the chunk offsets along the way. This utility
24  * presently only operates on uncompressed moov atoms.
25  */
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <inttypes.h>
30 #include <string.h>
31 #include <limits.h>
32 
33 #ifdef __MINGW32__
34 #undef fseeko
35 #define fseeko(x, y, z) fseeko64(x, y, z)
36 #undef ftello
37 #define ftello(x) ftello64(x)
38 #elif defined(_WIN32)
39 #undef fseeko
40 #define fseeko(x, y, z) _fseeki64(x, y, z)
41 #undef ftello
42 #define ftello(x) _ftelli64(x)
43 #endif
44 
45 #define MIN(a,b) ((a) > (b) ? (b) : (a))
46 
47 #define BE_32(x) (((uint32_t)(((uint8_t*)(x))[0]) << 24) | \
48  (((uint8_t*)(x))[1] << 16) | \
49  (((uint8_t*)(x))[2] << 8) | \
50  ((uint8_t*)(x))[3])
51 
52 #define BE_64(x) (((uint64_t)(((uint8_t*)(x))[0]) << 56) | \
53  ((uint64_t)(((uint8_t*)(x))[1]) << 48) | \
54  ((uint64_t)(((uint8_t*)(x))[2]) << 40) | \
55  ((uint64_t)(((uint8_t*)(x))[3]) << 32) | \
56  ((uint64_t)(((uint8_t*)(x))[4]) << 24) | \
57  ((uint64_t)(((uint8_t*)(x))[5]) << 16) | \
58  ((uint64_t)(((uint8_t*)(x))[6]) << 8) | \
59  ((uint64_t)( (uint8_t*)(x))[7]))
60 
61 #define AV_WB32(p, val) { \
62  ((uint8_t*)(p))[0] = ((val) >> 24) & 0xff; \
63  ((uint8_t*)(p))[1] = ((val) >> 16) & 0xff; \
64  ((uint8_t*)(p))[2] = ((val) >> 8) & 0xff; \
65  ((uint8_t*)(p))[3] = (val) & 0xff; \
66  }
67 
68 #define AV_WB64(p, val) { \
69  AV_WB32(p, (val) >> 32) \
70  AV_WB32(p + 4, val) \
71  }
72 
73 #define BE_FOURCC(ch0, ch1, ch2, ch3) \
74  ( (uint32_t)(unsigned char)(ch3) | \
75  ((uint32_t)(unsigned char)(ch2) << 8) | \
76  ((uint32_t)(unsigned char)(ch1) << 16) | \
77  ((uint32_t)(unsigned char)(ch0) << 24) )
78 
79 #define QT_ATOM BE_FOURCC
80 /* top level atoms */
81 #define FREE_ATOM QT_ATOM('f', 'r', 'e', 'e')
82 #define JUNK_ATOM QT_ATOM('j', 'u', 'n', 'k')
83 #define MDAT_ATOM QT_ATOM('m', 'd', 'a', 't')
84 #define MOOV_ATOM QT_ATOM('m', 'o', 'o', 'v')
85 #define PNOT_ATOM QT_ATOM('p', 'n', 'o', 't')
86 #define SKIP_ATOM QT_ATOM('s', 'k', 'i', 'p')
87 #define WIDE_ATOM QT_ATOM('w', 'i', 'd', 'e')
88 #define PICT_ATOM QT_ATOM('P', 'I', 'C', 'T')
89 #define FTYP_ATOM QT_ATOM('f', 't', 'y', 'p')
90 #define UUID_ATOM QT_ATOM('u', 'u', 'i', 'd')
91 
92 #define CMOV_ATOM QT_ATOM('c', 'm', 'o', 'v')
93 #define TRAK_ATOM QT_ATOM('t', 'r', 'a', 'k')
94 #define MDIA_ATOM QT_ATOM('m', 'd', 'i', 'a')
95 #define MINF_ATOM QT_ATOM('m', 'i', 'n', 'f')
96 #define STBL_ATOM QT_ATOM('s', 't', 'b', 'l')
97 #define STCO_ATOM QT_ATOM('s', 't', 'c', 'o')
98 #define CO64_ATOM QT_ATOM('c', 'o', '6', '4')
99 
100 #define ATOM_PREAMBLE_SIZE 8
101 #define COPY_BUFFER_SIZE 33554432
102 #define MAX_FTYP_ATOM_SIZE 1048576
103 
104 typedef struct {
105  uint32_t type;
106  uint32_t header_size;
107  uint64_t size;
108  unsigned char *data;
109 } atom_t;
110 
111 typedef struct {
112  uint64_t moov_atom_size;
114  uint64_t stco_data_size;
116  uint32_t depth;
118 
119 typedef struct {
120  unsigned char *dest;
122  uint64_t new_moov_size;
124 
125 typedef int (*parse_atoms_callback_t)(void *context, atom_t *atom);
126 
127 static int parse_atoms(
128  unsigned char *buf,
129  uint64_t size,
131  void *context)
132 {
133  unsigned char *pos = buf;
134  unsigned char *end = pos + size;
135  atom_t atom;
136  int ret;
137 
138  while (end - pos >= ATOM_PREAMBLE_SIZE) {
139  atom.size = BE_32(pos);
140  atom.type = BE_32(pos + 4);
141  pos += ATOM_PREAMBLE_SIZE;
143 
144  switch (atom.size) {
145  case 1:
146  if (end - pos < 8) {
147  fprintf(stderr, "not enough room for 64 bit atom size\n");
148  return -1;
149  }
150 
151  atom.size = BE_64(pos);
152  pos += 8;
153  atom.header_size = ATOM_PREAMBLE_SIZE + 8;
154  break;
155 
156  case 0:
157  atom.size = ATOM_PREAMBLE_SIZE + end - pos;
158  break;
159  }
160 
161  if (atom.size < atom.header_size) {
162  fprintf(stderr, "atom size %"PRIu64" too small\n", atom.size);
163  return -1;
164  }
165 
166  atom.size -= atom.header_size;
167 
168  if (atom.size > end - pos) {
169  fprintf(stderr, "atom size %"PRIu64" too big\n", atom.size);
170  return -1;
171  }
172 
173  atom.data = pos;
174  ret = callback(context, &atom);
175  if (ret < 0) {
176  return ret;
177  }
178 
179  pos += atom.size;
180  }
181 
182  return 0;
183 }
184 
186 {
187  uint32_t current_offset;
188  uint32_t offset_count;
189  unsigned char *pos;
190  unsigned char *end;
191 
192  printf(" patching stco atom...\n");
193  if (atom->size < 8) {
194  fprintf(stderr, "stco atom size %"PRIu64" too small\n", atom->size);
195  return -1;
196  }
197 
198  offset_count = BE_32(atom->data + 4);
199  if (offset_count > (atom->size - 8) / 4) {
200  fprintf(stderr, "stco offset count %"PRIu32" too big\n", offset_count);
201  return -1;
202  }
203 
204  context->stco_offset_count += offset_count;
205  context->stco_data_size += atom->size - 8;
206 
207  for (pos = atom->data + 8, end = pos + offset_count * 4;
208  pos < end;
209  pos += 4) {
210  current_offset = BE_32(pos);
211  if (current_offset > UINT_MAX - context->moov_atom_size) {
212  context->stco_overflow = 1;
213  }
214  current_offset += context->moov_atom_size;
215  AV_WB32(pos, current_offset);
216  }
217 
218  return 0;
219 }
220 
222 {
223  uint64_t current_offset;
224  uint32_t offset_count;
225  unsigned char *pos;
226  unsigned char *end;
227 
228  printf(" patching co64 atom...\n");
229  if (atom->size < 8) {
230  fprintf(stderr, "co64 atom size %"PRIu64" too small\n", atom->size);
231  return -1;
232  }
233 
234  offset_count = BE_32(atom->data + 4);
235  if (offset_count > (atom->size - 8) / 8) {
236  fprintf(stderr, "co64 offset count %"PRIu32" too big\n", offset_count);
237  return -1;
238  }
239 
240  for (pos = atom->data + 8, end = pos + offset_count * 8;
241  pos < end;
242  pos += 8) {
243  current_offset = BE_64(pos);
244  current_offset += context->moov_atom_size;
245  AV_WB64(pos, current_offset);
246  }
247 
248  return 0;
249 }
250 
251 static int update_chunk_offsets_callback(void *ctx, atom_t *atom)
252 {
254  int ret;
255 
256  switch (atom->type) {
257  case STCO_ATOM:
258  return update_stco_offsets(context, atom);
259 
260  case CO64_ATOM:
261  return update_co64_offsets(context, atom);
262 
263  case MOOV_ATOM:
264  case TRAK_ATOM:
265  case MDIA_ATOM:
266  case MINF_ATOM:
267  case STBL_ATOM:
268  context->depth++;
269  if (context->depth > 10) {
270  fprintf(stderr, "atoms too deeply nested\n");
271  return -1;
272  }
273 
274  ret = parse_atoms(
275  atom->data,
276  atom->size,
278  context);
279  context->depth--;
280  return ret;
281  }
282 
283  return 0;
284 }
285 
286 static void set_atom_size(unsigned char *header, uint32_t header_size, uint64_t size)
287 {
288  switch (header_size) {
289  case 8:
290  AV_WB32(header, size);
291  break;
292 
293  case 16:
294  AV_WB64(header + 8, size);
295  break;
296  }
297 }
298 
300 {
301  unsigned char *pos;
302  unsigned char *end;
303  uint64_t new_offset;
304  uint32_t offset_count;
305  uint32_t original_offset;
306 
307  /* Note: not performing validations since they were performed on the first pass */
308 
309  offset_count = BE_32(atom->data + 4);
310 
311  /* write the header */
312  memcpy(context->dest, atom->data - atom->header_size, atom->header_size + 8);
313  AV_WB32(context->dest + 4, CO64_ATOM);
314  set_atom_size(context->dest, atom->header_size, atom->header_size + 8 + offset_count * 8);
315  context->dest += atom->header_size + 8;
316 
317  /* write the data */
318  for (pos = atom->data + 8, end = pos + offset_count * 4;
319  pos < end;
320  pos += 4) {
321  original_offset = BE_32(pos) - context->original_moov_size;
322  new_offset = (uint64_t)original_offset + context->new_moov_size;
323  AV_WB64(context->dest, new_offset);
324  context->dest += 8;
325  }
326 }
327 
328 static int upgrade_stco_callback(void *ctx, atom_t *atom)
329 {
331  unsigned char *start_pos;
332  uint64_t copy_size;
333 
334  switch (atom->type) {
335  case STCO_ATOM:
336  upgrade_stco_atom(context, atom);
337  break;
338 
339  case MOOV_ATOM:
340  case TRAK_ATOM:
341  case MDIA_ATOM:
342  case MINF_ATOM:
343  case STBL_ATOM:
344  /* write the atom header */
345  memcpy(context->dest, atom->data - atom->header_size, atom->header_size);
346  start_pos = context->dest;
347  context->dest += atom->header_size;
348 
349  /* parse internal atoms*/
350  if (parse_atoms(
351  atom->data,
352  atom->size,
354  context) < 0) {
355  return -1;
356  }
357 
358  /* update the atom size */
359  set_atom_size(start_pos, atom->header_size, context->dest - start_pos);
360  break;
361 
362  default:
363  copy_size = atom->header_size + atom->size;
364  memcpy(context->dest, atom->data - atom->header_size, copy_size);
365  context->dest += copy_size;
366  break;
367  }
368 
369  return 0;
370 }
371 
372 static int update_moov_atom(
373  unsigned char **moov_atom,
374  uint64_t *moov_atom_size)
375 {
377  upgrade_stco_context_t upgrade_context;
378  unsigned char *new_moov_atom;
379 
380  update_context.moov_atom_size = *moov_atom_size;
381 
382  if (parse_atoms(
383  *moov_atom,
384  *moov_atom_size,
386  &update_context) < 0) {
387  return -1;
388  }
389 
390  if (!update_context.stco_overflow) {
391  return 0;
392  }
393 
394  printf(" upgrading stco atoms to co64...\n");
395  upgrade_context.new_moov_size = *moov_atom_size +
396  update_context.stco_offset_count * 8 -
397  update_context.stco_data_size;
398 
399  new_moov_atom = malloc(upgrade_context.new_moov_size);
400  if (new_moov_atom == NULL) {
401  fprintf(stderr, "could not allocate %"PRIu64" bytes for updated moov atom\n",
402  upgrade_context.new_moov_size);
403  return -1;
404  }
405 
406  upgrade_context.original_moov_size = *moov_atom_size;
407  upgrade_context.dest = new_moov_atom;
408 
409  if (parse_atoms(
410  *moov_atom,
411  *moov_atom_size,
413  &upgrade_context) < 0) {
414  free(new_moov_atom);
415  return -1;
416  }
417 
418  free(*moov_atom);
419  *moov_atom = new_moov_atom;
420  *moov_atom_size = upgrade_context.new_moov_size;
421 
422  if (upgrade_context.dest != *moov_atom + *moov_atom_size) {
423  fprintf(stderr, "unexpected - wrong number of moov bytes written\n");
424  return -1;
425  }
426 
427  return 0;
428 }
429 
430 int main(int argc, char *argv[])
431 {
432  FILE *infile = NULL;
433  FILE *outfile = NULL;
434  unsigned char atom_bytes[ATOM_PREAMBLE_SIZE];
435  uint32_t atom_type = 0;
436  uint64_t atom_size = 0;
437  uint64_t atom_offset = 0;
438  int64_t last_offset;
439  unsigned char *moov_atom = NULL;
440  unsigned char *ftyp_atom = NULL;
441  uint64_t moov_atom_size;
442  uint64_t ftyp_atom_size = 0;
443  int64_t start_offset = 0;
444  unsigned char *copy_buffer = NULL;
445  int bytes_to_copy;
446  uint64_t free_size = 0;
447  uint64_t moov_size = 0;
448 
449  if (argc != 3) {
450  printf("Usage: qt-faststart <infile.mov> <outfile.mov>\n"
451  "Note: alternatively you can use -movflags +faststart in ffmpeg\n");
452  return 0;
453  }
454 
455  if (!strcmp(argv[1], argv[2])) {
456  fprintf(stderr, "input and output files need to be different\n");
457  return 1;
458  }
459 
460  infile = fopen(argv[1], "rb");
461  if (!infile) {
462  perror(argv[1]);
463  goto error_out;
464  }
465 
466  /* traverse through the atoms in the file to make sure that 'moov' is
467  * at the end */
468  while (!feof(infile)) {
469  if (fread(atom_bytes, ATOM_PREAMBLE_SIZE, 1, infile) != 1) {
470  break;
471  }
472  atom_size = BE_32(&atom_bytes[0]);
473  atom_type = BE_32(&atom_bytes[4]);
474 
475  /* keep ftyp atom */
476  if (atom_type == FTYP_ATOM) {
477  if (atom_size > MAX_FTYP_ATOM_SIZE) {
478  fprintf(stderr, "ftyp atom size %"PRIu64" too big\n",
479  atom_size);
480  goto error_out;
481  }
482  ftyp_atom_size = atom_size;
483  free(ftyp_atom);
484  ftyp_atom = malloc(ftyp_atom_size);
485  if (!ftyp_atom) {
486  fprintf(stderr, "could not allocate %"PRIu64" bytes for ftyp atom\n",
487  atom_size);
488  goto error_out;
489  }
490  if (fseeko(infile, -ATOM_PREAMBLE_SIZE, SEEK_CUR) ||
491  fread(ftyp_atom, atom_size, 1, infile) != 1 ||
492  (start_offset = ftello(infile)) < 0) {
493  perror(argv[1]);
494  goto error_out;
495  }
496  } else {
497  int ret;
498  /* 64-bit special case */
499  if (atom_size == 1) {
500  if (fread(atom_bytes, ATOM_PREAMBLE_SIZE, 1, infile) != 1) {
501  break;
502  }
503  atom_size = BE_64(&atom_bytes[0]);
504  ret = fseeko(infile, atom_size - ATOM_PREAMBLE_SIZE * 2, SEEK_CUR);
505  } else {
506  ret = fseeko(infile, atom_size - ATOM_PREAMBLE_SIZE, SEEK_CUR);
507  }
508  if (ret) {
509  perror(argv[1]);
510  goto error_out;
511  }
512  }
513  printf("%c%c%c%c %10"PRIu64" %"PRIu64"\n",
514  (atom_type >> 24) & 255,
515  (atom_type >> 16) & 255,
516  (atom_type >> 8) & 255,
517  (atom_type >> 0) & 255,
518  atom_offset,
519  atom_size);
520  if ((atom_type != FREE_ATOM) &&
521  (atom_type != JUNK_ATOM) &&
522  (atom_type != MDAT_ATOM) &&
523  (atom_type != MOOV_ATOM) &&
524  (atom_type != PNOT_ATOM) &&
525  (atom_type != SKIP_ATOM) &&
526  (atom_type != WIDE_ATOM) &&
527  (atom_type != PICT_ATOM) &&
528  (atom_type != UUID_ATOM) &&
529  (atom_type != FTYP_ATOM)) {
530  fprintf(stderr, "encountered non-QT top-level atom (is this a QuickTime file?)\n");
531  break;
532  }
533  atom_offset += atom_size;
534 
535  /* The atom header is 8 (or 16 bytes), if the atom size (which
536  * includes these 8 or 16 bytes) is less than that, we won't be
537  * able to continue scanning sensibly after this atom, so break. */
538  if (atom_size < 8)
539  break;
540 
541  if (atom_type == MOOV_ATOM)
542  moov_size = atom_size;
543 
544  if (moov_size && atom_type == FREE_ATOM) {
545  free_size += atom_size;
546  atom_type = MOOV_ATOM;
547  atom_size = moov_size;
548  }
549  }
550 
551  if (atom_type != MOOV_ATOM) {
552  printf("last atom in file was not a moov atom\n");
553  free(ftyp_atom);
554  fclose(infile);
555  return 0;
556  }
557 
558  if (atom_size < 16) {
559  fprintf(stderr, "bad moov atom size\n");
560  goto error_out;
561  }
562 
563  /* moov atom was, in fact, the last atom in the chunk; load the whole
564  * moov atom */
565  if (fseeko(infile, -(atom_size + free_size), SEEK_END)) {
566  perror(argv[1]);
567  goto error_out;
568  }
569  last_offset = ftello(infile);
570  if (last_offset < 0) {
571  perror(argv[1]);
572  goto error_out;
573  }
574  moov_atom_size = atom_size;
575  moov_atom = malloc(moov_atom_size);
576  if (!moov_atom) {
577  fprintf(stderr, "could not allocate %"PRIu64" bytes for moov atom\n", atom_size);
578  goto error_out;
579  }
580  if (fread(moov_atom, atom_size, 1, infile) != 1) {
581  perror(argv[1]);
582  goto error_out;
583  }
584 
585  /* this utility does not support compressed atoms yet, so disqualify
586  * files with compressed QT atoms */
587  if (BE_32(&moov_atom[12]) == CMOV_ATOM) {
588  fprintf(stderr, "this utility does not support compressed moov atoms yet\n");
589  goto error_out;
590  }
591 
592  /* close; will be re-opened later */
593  fclose(infile);
594  infile = NULL;
595 
596  if (update_moov_atom(&moov_atom, &moov_atom_size) < 0) {
597  goto error_out;
598  }
599 
600  /* re-open the input file and open the output file */
601  infile = fopen(argv[1], "rb");
602  if (!infile) {
603  perror(argv[1]);
604  goto error_out;
605  }
606 
607  if (start_offset > 0) { /* seek after ftyp atom */
608  if (fseeko(infile, start_offset, SEEK_SET)) {
609  perror(argv[1]);
610  goto error_out;
611  }
612 
613  last_offset -= start_offset;
614  }
615 
616  outfile = fopen(argv[2], "wb");
617  if (!outfile) {
618  perror(argv[2]);
619  goto error_out;
620  }
621 
622  /* dump the same ftyp atom */
623  if (ftyp_atom_size > 0) {
624  printf(" writing ftyp atom...\n");
625  if (fwrite(ftyp_atom, ftyp_atom_size, 1, outfile) != 1) {
626  perror(argv[2]);
627  goto error_out;
628  }
629  }
630 
631  /* dump the new moov atom */
632  printf(" writing moov atom...\n");
633  if (fwrite(moov_atom, moov_atom_size, 1, outfile) != 1) {
634  perror(argv[2]);
635  goto error_out;
636  }
637 
638  /* copy the remainder of the infile, from offset 0 -> last_offset - 1 */
639  bytes_to_copy = MIN(COPY_BUFFER_SIZE, last_offset);
640  copy_buffer = malloc(bytes_to_copy);
641  if (!copy_buffer) {
642  fprintf(stderr, "could not allocate %d bytes for copy_buffer\n", bytes_to_copy);
643  goto error_out;
644  }
645  printf(" copying rest of file...\n");
646  while (last_offset) {
647  bytes_to_copy = MIN(bytes_to_copy, last_offset);
648 
649  if (fread(copy_buffer, bytes_to_copy, 1, infile) != 1) {
650  perror(argv[1]);
651  goto error_out;
652  }
653  if (fwrite(copy_buffer, bytes_to_copy, 1, outfile) != 1) {
654  perror(argv[2]);
655  goto error_out;
656  }
657  last_offset -= bytes_to_copy;
658  }
659 
660  fclose(infile);
661  fclose(outfile);
662  free(moov_atom);
663  free(ftyp_atom);
664  free(copy_buffer);
665 
666  return 0;
667 
668 error_out:
669  if (infile)
670  fclose(infile);
671  if (outfile)
672  fclose(outfile);
673  free(moov_atom);
674  free(ftyp_atom);
675  free(copy_buffer);
676  return 1;
677 }
static int parse_atoms(unsigned char *buf, uint64_t size, parse_atoms_callback_t callback, void *context)
Definition: qt-faststart.c:127
#define NULL
Definition: coverity.c:32
int(* parse_atoms_callback_t)(void *context, atom_t *atom)
Definition: qt-faststart.c:125
#define MOOV_ATOM
Definition: qt-faststart.c:84
#define MIN(a, b)
Definition: qt-faststart.c:45
#define BE_32(x)
Definition: qt-faststart.c:47
uint64_t size
Definition: qt-faststart.c:107
#define COPY_BUFFER_SIZE
Definition: qt-faststart.c:101
static int update_co64_offsets(update_chunk_offsets_context_t *context, atom_t *atom)
Definition: qt-faststart.c:221
#define FREE_ATOM
Definition: qt-faststart.c:81
unsigned char * dest
Definition: qt-faststart.c:120
static int update_moov_atom(unsigned char **moov_atom, uint64_t *moov_atom_size)
Definition: qt-faststart.c:372
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
#define MDIA_ATOM
Definition: qt-faststart.c:94
#define AV_WB32(p, val)
Definition: qt-faststart.c:61
#define PNOT_ATOM
Definition: qt-faststart.c:85
#define ATOM_PREAMBLE_SIZE
Definition: qt-faststart.c:100
#define JUNK_ATOM
Definition: qt-faststart.c:82
uint32_t type
Definition: qt-faststart.c:105
ptrdiff_t size
Definition: opengl_enc.c:100
static const uint8_t header[24]
Definition: sdr2.c:67
#define CMOV_ATOM
Definition: qt-faststart.c:92
#define MDAT_ATOM
Definition: qt-faststart.c:83
#define CO64_ATOM
Definition: qt-faststart.c:98
#define MAX_FTYP_ATOM_SIZE
Definition: qt-faststart.c:102
#define TRAK_ATOM
Definition: qt-faststart.c:93
#define MINF_ATOM
Definition: qt-faststart.c:95
#define UUID_ATOM
Definition: qt-faststart.c:90
static void callback(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time, enum dshowDeviceType devtype)
Definition: dshow.c:161
static int upgrade_stco_callback(void *ctx, atom_t *atom)
Definition: qt-faststart.c:328
AVFormatContext * ctx
Definition: movenc.c:48
uint32_t header_size
Definition: qt-faststart.c:106
unsigned char * data
Definition: qt-faststart.c:108
static void update_context(VignetteContext *s, AVFilterLink *inlink, AVFrame *frame)
Definition: vf_vignette.c:161
static void set_atom_size(unsigned char *header, uint32_t header_size, uint64_t size)
Definition: qt-faststart.c:286
void * buf
Definition: avisynth_c.h:766
#define STCO_ATOM
Definition: qt-faststart.c:97
#define WIDE_ATOM
Definition: qt-faststart.c:87
#define STBL_ATOM
Definition: qt-faststart.c:96
#define BE_64(x)
Definition: qt-faststart.c:52
static int update_chunk_offsets_callback(void *ctx, atom_t *atom)
Definition: qt-faststart.c:251
#define FTYP_ATOM
Definition: qt-faststart.c:89
int
int main(int argc, char *argv[])
Definition: qt-faststart.c:430
printf("static const uint8_t my_array[100] = {\n")
#define AV_WB64(p, val)
Definition: qt-faststart.c:68
#define SKIP_ATOM
Definition: qt-faststart.c:86
#define PICT_ATOM
Definition: qt-faststart.c:88
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 keep it simple and lowercase description are in without and describe what they for example set the foo of the bar offset is the offset of the field in your local context
static int update_stco_offsets(update_chunk_offsets_context_t *context, atom_t *atom)
Definition: qt-faststart.c:185
FILE * outfile
Definition: audiogen.c:96
static void upgrade_stco_atom(upgrade_stco_context_t *context, atom_t *atom)
Definition: qt-faststart.c:299