qt-faststart: Avoid leaking memory if encountering a file with double ftyp atoms
[ffmpeg.git] / tools / qt-faststart.c
index 2cbf12b..f48ffc0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * qt-faststart.c, v0.1
+ * qt-faststart.c, v0.2
  * by Mike Melanson (melanson@pcisys.net)
  * This file is placed in the public domain. Use the program however you
  * see fit.
@@ -7,8 +7,12 @@
  * This utility rearranges a Quicktime file such that the moov atom
  * is in front of the data, thus facilitating network streaming.
  *
- * Compile this program using:
- *  make qt-faststart
+ * To compile this program, start from the base directory from which you
+ * are building FFmpeg and type:
+ *  make tools/qt-faststart
+ * The qt-faststart program will be built in the tools/ directory. If you
+ * do not build the program in this manner, correct results are not
+ * guaranteed, particularly on 64-bit platforms.
  * Invoke the program with:
  *  qt-faststart <infile.mov> <outfile.mov>
  *
@@ -60,6 +64,7 @@
 #define WIDE_ATOM QT_ATOM('w', 'i', 'd', 'e')
 #define PICT_ATOM QT_ATOM('P', 'I', 'C', 'T')
 #define FTYP_ATOM QT_ATOM('f', 't', 'y', 'p')
+#define UUID_ATOM QT_ATOM('u', 'u', 'i', 'd')
 
 #define CMOV_ATOM QT_ATOM('c', 'm', 'o', 'v')
 #define STCO_ATOM QT_ATOM('s', 't', 'c', 'o')
@@ -75,6 +80,7 @@ int main(int argc, char *argv[])
     unsigned char atom_bytes[ATOM_PREAMBLE_SIZE];
     uint32_t atom_type = 0;
     uint64_t atom_size = 0;
+    uint64_t atom_offset = 0;
     uint64_t last_offset;
     unsigned char *moov_atom;
     unsigned char *ftyp_atom = 0;
@@ -107,25 +113,13 @@ int main(int argc, char *argv[])
         atom_size = (uint32_t)BE_32(&atom_bytes[0]);
         atom_type = BE_32(&atom_bytes[4]);
 
-        if ((atom_type != FREE_ATOM) &&
-            (atom_type != JUNK_ATOM) &&
-            (atom_type != MDAT_ATOM) &&
-            (atom_type != MOOV_ATOM) &&
-            (atom_type != PNOT_ATOM) &&
-            (atom_type != SKIP_ATOM) &&
-            (atom_type != WIDE_ATOM) &&
-            (atom_type != PICT_ATOM) &&
-            (atom_type != FTYP_ATOM)) {
-            printf ("encountered non-QT top-level atom (is this a Quicktime file?)\n");
-            break;
-        }
-
         /* keep ftyp atom */
         if (atom_type == FTYP_ATOM) {
             ftyp_atom_size = atom_size;
+            free(ftyp_atom);
             ftyp_atom = malloc(ftyp_atom_size);
             if (!ftyp_atom) {
-                printf ("could not allocate 0x%llX byte for ftyp atom\n",
+                printf ("could not allocate %"PRIu64" byte for ftyp atom\n",
                         atom_size);
                 fclose(infile);
                 return 1;
@@ -138,8 +132,7 @@ int main(int argc, char *argv[])
                 return 1;
             }
             start_offset = ftello(infile);
-            continue;
-        }
+        } else {
 
         /* 64-bit special case */
         if (atom_size == 1) {
@@ -152,9 +145,32 @@ int main(int argc, char *argv[])
             fseeko(infile, atom_size - ATOM_PREAMBLE_SIZE, SEEK_CUR);
         }
     }
+        printf("%c%c%c%c %10"PRIu64" %"PRIu64"\n",
+               (atom_type >> 24) & 255,
+               (atom_type >> 16) & 255,
+               (atom_type >>  8) & 255,
+               (atom_type >>  0) & 255,
+               atom_offset,
+               atom_size);
+        if ((atom_type != FREE_ATOM) &&
+            (atom_type != JUNK_ATOM) &&
+            (atom_type != MDAT_ATOM) &&
+            (atom_type != MOOV_ATOM) &&
+            (atom_type != PNOT_ATOM) &&
+            (atom_type != SKIP_ATOM) &&
+            (atom_type != WIDE_ATOM) &&
+            (atom_type != PICT_ATOM) &&
+            (atom_type != UUID_ATOM) &&
+            (atom_type != FTYP_ATOM)) {
+            printf ("encountered non-QT top-level atom (is this a Quicktime file?)\n");
+            break;
+        }
+        atom_offset += atom_size;
+    }
 
     if (atom_type != MOOV_ATOM) {
         printf ("last atom in file was not a moov atom\n");
+        free(ftyp_atom);
         fclose(infile);
         return 0;
     }
@@ -166,14 +182,16 @@ int main(int argc, char *argv[])
     moov_atom_size = atom_size;
     moov_atom = malloc(moov_atom_size);
     if (!moov_atom) {
-        printf ("could not allocate 0x%llX byte for moov atom\n",
+        printf ("could not allocate %"PRIu64" byte for moov atom\n",
             atom_size);
+        free(ftyp_atom);
         fclose(infile);
         return 1;
     }
     if (fread(moov_atom, atom_size, 1, infile) != 1) {
         perror(argv[1]);
         free(moov_atom);
+        free(ftyp_atom);
         fclose(infile);
         return 1;
     }
@@ -183,6 +201,7 @@ int main(int argc, char *argv[])
     if (BE_32(&moov_atom[12]) == CMOV_ATOM) {
         printf ("this utility does not support compressed moov atoms yet\n");
         free(moov_atom);
+        free(ftyp_atom);
         fclose(infile);
         return 1;
     }
@@ -199,6 +218,7 @@ int main(int argc, char *argv[])
             if (i + atom_size - 4 > moov_atom_size) {
                 printf (" bad atom size\n");
                 free(moov_atom);
+                free(ftyp_atom);
                 return 1;
             }
             offset_count = BE_32(&moov_atom[i + 8]);
@@ -217,6 +237,7 @@ int main(int argc, char *argv[])
             if (i + atom_size - 4 > moov_atom_size) {
                 printf (" bad atom size\n");
                 free(moov_atom);
+                free(ftyp_atom);
                 return 1;
             }
             offset_count = BE_32(&moov_atom[i + 8]);
@@ -241,6 +262,7 @@ int main(int argc, char *argv[])
     if (!infile) {
         perror(argv[1]);
         free(moov_atom);
+        free(ftyp_atom);
         return 1;
     }
 
@@ -254,6 +276,7 @@ int main(int argc, char *argv[])
         perror(argv[2]);
         fclose(outfile);
         free(moov_atom);
+        free(ftyp_atom);
         return 1;
     }
 
@@ -296,8 +319,7 @@ int main(int argc, char *argv[])
     fclose(infile);
     fclose(outfile);
     free(moov_atom);
-    if (ftyp_atom_size > 0)
-        free(ftyp_atom);
+    free(ftyp_atom);
 
     return 0;
 
@@ -305,7 +327,6 @@ error_out:
     fclose(infile);
     fclose(outfile);
     free(moov_atom);
-    if (ftyp_atom_size > 0)
-        free(ftyp_atom);
+    free(ftyp_atom);
     return 1;
 }