Merge "MPEG4Writer: adjust the whole CTTS table" into nyc-mr1-dev
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index bbc75d6..21a5faa 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -372,6 +372,7 @@
       mInitCheck(NO_INIT),
       mHasVideo(false),
       mHeaderTimescale(0),
+      mIsQT(false),
       mFirstTrack(NULL),
       mLastTrack(NULL),
       mFileMetaData(new MetaData),
@@ -915,6 +916,7 @@
         case FOURCC('s', 'i', 'n', 'f'):
         case FOURCC('s', 'c', 'h', 'i'):
         case FOURCC('e', 'd', 't', 's'):
+        case FOURCC('w', 'a', 'v', 'e'):
         {
             if (chunk_type == FOURCC('m', 'o', 'o', 'f') && !mMoofFound) {
                 // store the offset of the first segment
@@ -1372,6 +1374,13 @@
         case FOURCC('s', 'a', 'm', 'r'):
         case FOURCC('s', 'a', 'w', 'b'):
         {
+            if (mIsQT && chunk_type == FOURCC('m', 'p', '4', 'a')
+                    && depth >= 1 && mPath[depth - 1] == FOURCC('w', 'a', 'v', 'e')) {
+                // Ignore mp4a embedded in QT wave atom
+                *offset += chunk_size;
+                break;
+            }
+
             uint8_t buffer[8 + 20];
             if (chunk_data_size < (ssize_t)sizeof(buffer)) {
                 // Basic AudioSampleEntry size.
@@ -1384,6 +1393,7 @@
             }
 
             uint16_t data_ref_index __unused = U16_AT(&buffer[6]);
+            uint16_t version = U16_AT(&buffer[8]);
             uint32_t num_channels = U16_AT(&buffer[16]);
 
             uint16_t sample_size = U16_AT(&buffer[18]);
@@ -1392,6 +1402,42 @@
             if (mLastTrack == NULL)
                 return ERROR_MALFORMED;
 
+            off64_t stop_offset = *offset + chunk_size;
+            *offset = data_offset + sizeof(buffer);
+
+            if (mIsQT && chunk_type == FOURCC('m', 'p', '4', 'a')) {
+                if (version == 1) {
+                    if (mDataSource->readAt(*offset, buffer, 16) < 16) {
+                        return ERROR_IO;
+                    }
+
+#if 0
+                    U32_AT(buffer);  // samples per packet
+                    U32_AT(&buffer[4]);  // bytes per packet
+                    U32_AT(&buffer[8]);  // bytes per frame
+                    U32_AT(&buffer[12]);  // bytes per sample
+#endif
+                    *offset += 16;
+                } else if (version == 2) {
+                    uint8_t v2buffer[36];
+                    if (mDataSource->readAt(*offset, v2buffer, 36) < 36) {
+                        return ERROR_IO;
+                    }
+
+#if 0
+                    U32_AT(v2buffer);  // size of struct only
+                    sample_rate = (uint32_t)U64_AT(&v2buffer[4]);  // audio sample rate
+                    num_channels = U32_AT(&v2buffer[12]);  // num audio channels
+                    U32_AT(&v2buffer[16]);  // always 0x7f000000
+                    sample_size = (uint16_t)U32_AT(&v2buffer[20]);  // const bits per channel
+                    U32_AT(&v2buffer[24]);  // format specifc flags
+                    U32_AT(&v2buffer[28]);  // const bytes per audio packet
+                    U32_AT(&v2buffer[32]);  // const LPCM frames per audio packet
+#endif
+                    *offset += 36;
+                }
+            }
+
             if (chunk_type != FOURCC('e', 'n', 'c', 'a')) {
                 // if the chunk type is enca, we'll get the type from the sinf/frma box later
                 mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
@@ -1402,8 +1448,6 @@
             mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
             mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
 
-            off64_t stop_offset = *offset + chunk_size;
-            *offset = data_offset + sizeof(buffer);
             while (*offset < stop_offset) {
                 status_t err = parseChunk(offset, depth + 1);
                 if (err != OK) {
@@ -2240,6 +2284,38 @@
             return UNKNOWN_ERROR; // stop parsing after sidx
         }
 
+        case FOURCC('f', 't', 'y', 'p'):
+        {
+            if (chunk_data_size < 8 || depth != 0) {
+                return ERROR_MALFORMED;
+            }
+
+            off64_t stop_offset = *offset + chunk_size;
+            uint32_t numCompatibleBrands = (chunk_data_size - 8) / 4;
+            for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
+                if (i == 1) {
+                    // Skip this index, it refers to the minorVersion,
+                    // not a brand.
+                    continue;
+                }
+
+                uint32_t brand;
+                if (mDataSource->readAt(data_offset + 4 * i, &brand, 4) < 4) {
+                    return ERROR_MALFORMED;
+                }
+
+                brand = ntohl(brand);
+                if (brand == FOURCC('q', 't', ' ', ' ')) {
+                    mIsQT = true;
+                    break;
+                }
+            }
+
+            *offset = stop_offset;
+
+            break;
+        }
+
         default:
         {
             // check if we're parsing 'ilst' for meta keys
diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h
index 18b14e1..37c35e3 100644
--- a/media/libstagefright/include/MPEG4Extractor.h
+++ b/media/libstagefright/include/MPEG4Extractor.h
@@ -95,6 +95,7 @@
     status_t mInitCheck;
     bool mHasVideo;
     uint32_t mHeaderTimescale;
+    bool mIsQT;
 
     Track *mFirstTrack, *mLastTrack;