Merge "Cannot play a mov file with alac audio" into qt-dev
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 527bb77..9d5890c 100755
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -1197,45 +1197,16 @@
                         AMEDIAFORMAT_KEY_SAMPLE_RATE, sample_rate);
             }
 
-            // If format type is 'alac', it is necessary to get the parameters
-            // from a alac atom spreading behind the frma atom.
-            // See 'external/alac/ALACMagicCookieDescription.txt'.
-            if (original_fourcc == FOURCC("alac")) {
-                // Store ALAC magic cookie (decoder needs it).
-                uint8_t alacInfo[12];
-                data_offset = *offset;
-                if (mDataSource->readAt(
-                        data_offset, alacInfo, sizeof(alacInfo)) < (ssize_t)sizeof(alacInfo)) {
-                    return ERROR_IO;
+            if (!mIsQT && original_fourcc == FOURCC("alac")) {
+                off64_t tmpOffset = *offset;
+                status_t err = parseALACSampleEntry(&tmpOffset);
+                if (err != OK) {
+                    ALOGE("parseALACSampleEntry err:%d Line:%d", err, __LINE__);
+                    return err;
                 }
-                uint32_t size = U32_AT(&alacInfo[0]);
-                if ((size != ALAC_SPECIFIC_INFO_SIZE) ||
-                        (U32_AT(&alacInfo[4]) != FOURCC("alac")) ||
-                        (U32_AT(&alacInfo[8]) != 0)) {
-                    return ERROR_MALFORMED;
-                }
-
-                data_offset += sizeof(alacInfo);
-                uint8_t cookie[size - sizeof(alacInfo)];
-                if (mDataSource->readAt(
-                        data_offset, cookie, sizeof(cookie)) < (ssize_t)sizeof(cookie)) {
-                    return ERROR_IO;
-                }
-
-                uint8_t bitsPerSample = cookie[5];
-                AMediaFormat_setInt32(mLastTrack->meta,
-                        AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, bitsPerSample);
-                AMediaFormat_setInt32(mLastTrack->meta,
-                        AMEDIAFORMAT_KEY_CHANNEL_COUNT, cookie[9]);
-                AMediaFormat_setInt32(mLastTrack->meta,
-                        AMEDIAFORMAT_KEY_SAMPLE_RATE, U32_AT(&cookie[20]));
-                AMediaFormat_setBuffer(mLastTrack->meta,
-                        AMEDIAFORMAT_KEY_CSD_0, cookie, sizeof(cookie));
-
-                // Add the size of ALAC Specific Info (36 bytes) and terminator
-                // atom (8 bytes).
-                *offset += (size + 8);
+                *offset = tmpOffset + 8;
             }
+
             break;
         }
 
@@ -1653,7 +1624,18 @@
         case 0x6D730055: // "ms U" mp3 audio
         {
             if (mIsQT && depth >= 1 && mPath[depth - 1] == FOURCC("wave")) {
+
+                if (chunk_type == FOURCC("alac")) {
+                    off64_t offsetTmp = *offset;
+                    status_t err = parseALACSampleEntry(&offsetTmp);
+                    if (err != OK) {
+                        ALOGE("parseALACSampleEntry err:%d Line:%d", err, __LINE__);
+                        return err;
+                    }
+                }
+
                 // Ignore all atoms embedded in QT wave atom
+                ALOGV("Ignore all atoms embedded in QT wave atom");
                 *offset += chunk_size;
                 break;
             }
@@ -1792,39 +1774,14 @@
                 CHECK_EQ(*offset, stop_offset);
             }
 
-            if (chunk_type == FOURCC("alac")) {
-
-                // See 'external/alac/ALACMagicCookieDescription.txt for the detail'.
-                // Store ALAC magic cookie (decoder needs it).
-                uint8_t alacInfo[12];
+            if (!mIsQT && chunk_type == FOURCC("alac")) {
                 data_offset += sizeof(buffer);
-                if (mDataSource->readAt(
-                        data_offset, alacInfo, sizeof(alacInfo)) < (ssize_t)sizeof(alacInfo)) {
-                    return ERROR_IO;
-                }
-                uint32_t size = U32_AT(&alacInfo[0]);
-                if ((size != ALAC_SPECIFIC_INFO_SIZE) ||
-                        (U32_AT(&alacInfo[4]) != FOURCC("alac")) ||
-                        (U32_AT(&alacInfo[8]) != 0)) {
-                    return ERROR_MALFORMED;
-                }
-                data_offset += sizeof(alacInfo);
-                uint8_t cookie[size - sizeof(alacInfo)];
-                if (mDataSource->readAt(
-                        data_offset, cookie, sizeof(cookie)) < (ssize_t)sizeof(cookie)) {
-                    return ERROR_IO;
-                }
 
-                uint8_t bitsPerSample = cookie[5];
-                AMediaFormat_setInt32(mLastTrack->meta,
-                        AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, bitsPerSample);
-                AMediaFormat_setInt32(mLastTrack->meta,
-                        AMEDIAFORMAT_KEY_CHANNEL_COUNT, cookie[9]);
-                AMediaFormat_setInt32(mLastTrack->meta,
-                        AMEDIAFORMAT_KEY_SAMPLE_RATE, U32_AT(&cookie[20]));
-                AMediaFormat_setBuffer(mLastTrack->meta,
-                        AMEDIAFORMAT_KEY_CSD_0, cookie, sizeof(cookie));
-                data_offset += sizeof(cookie);
+                status_t err = parseALACSampleEntry(&data_offset);
+                if (err != OK) {
+                    ALOGE("parseALACSampleEntry err:%d Line:%d", err, __LINE__);
+                    return err;
+                }
                 *offset = data_offset;
                 CHECK_EQ(*offset, stop_offset);
             }
@@ -3289,6 +3246,45 @@
     return OK;
 }
 
+status_t MPEG4Extractor::parseALACSampleEntry(off64_t *offset) {
+    // See 'external/alac/ALACMagicCookieDescription.txt for the detail'.
+    // Store ALAC magic cookie (decoder needs it).
+    uint8_t alacInfo[12];
+    off64_t data_offset = *offset;
+
+    if (mDataSource->readAt(
+            data_offset, alacInfo, sizeof(alacInfo)) < (ssize_t)sizeof(alacInfo)) {
+        return ERROR_IO;
+    }
+    uint32_t size = U32_AT(&alacInfo[0]);
+    if ((size != ALAC_SPECIFIC_INFO_SIZE) ||
+            (U32_AT(&alacInfo[4]) != FOURCC("alac")) ||
+            (U32_AT(&alacInfo[8]) != 0)) {
+        ALOGV("Size:%u, U32_AT(&alacInfo[4]):%u, U32_AT(&alacInfo[8]):%u",
+            size, U32_AT(&alacInfo[4]), U32_AT(&alacInfo[8]));
+        return ERROR_MALFORMED;
+    }
+    data_offset += sizeof(alacInfo);
+    uint8_t cookie[size - sizeof(alacInfo)];
+    if (mDataSource->readAt(
+            data_offset, cookie, sizeof(cookie)) < (ssize_t)sizeof(cookie)) {
+        return ERROR_IO;
+    }
+
+    uint8_t bitsPerSample = cookie[5];
+    AMediaFormat_setInt32(mLastTrack->meta,
+            AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, bitsPerSample);
+    AMediaFormat_setInt32(mLastTrack->meta,
+            AMEDIAFORMAT_KEY_CHANNEL_COUNT, cookie[9]);
+    AMediaFormat_setInt32(mLastTrack->meta,
+            AMEDIAFORMAT_KEY_SAMPLE_RATE, U32_AT(&cookie[20]));
+    AMediaFormat_setBuffer(mLastTrack->meta,
+            AMEDIAFORMAT_KEY_CSD_0, cookie, sizeof(cookie));
+    data_offset += sizeof(cookie);
+    *offset = data_offset;
+    return OK;
+}
+
 status_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) {
   ALOGV("MPEG4Extractor::parseSegmentIndex");
 
diff --git a/media/extractors/mp4/MPEG4Extractor.h b/media/extractors/mp4/MPEG4Extractor.h
index e10bf8a..fcddbb8 100644
--- a/media/extractors/mp4/MPEG4Extractor.h
+++ b/media/extractors/mp4/MPEG4Extractor.h
@@ -179,6 +179,7 @@
     status_t parseAC3SpecificBox(off64_t offset);
     status_t parseEAC3SpecificBox(off64_t offset);
     status_t parseAC4SpecificBox(off64_t offset);
+    status_t parseALACSampleEntry(off64_t *offset);
     void adjustRawDefaultFrameSize();
 
     MPEG4Extractor(const MPEG4Extractor &);