Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 449c5619 authored by Wei Jia's avatar Wei Jia Committed by Android (Google) Code Review
Browse files

Merge "MPEG4EXtractor: add support of MP4A QT version 1 and 2." into nyc-mr1-dev

parents b4cb73e7 bb0b734c
Loading
Loading
Loading
Loading
+78 −2
Original line number Diff line number Diff line
@@ -372,6 +372,7 @@ MPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
      mInitCheck(NO_INIT),
      mHasVideo(false),
      mHeaderTimescale(0),
      mIsQT(false),
      mFirstTrack(NULL),
      mLastTrack(NULL),
      mFileMetaData(new MetaData),
@@ -915,6 +916,7 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
        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 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
        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 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
            }

            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 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
            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 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
            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 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
            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
+1 −0
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ private:
    status_t mInitCheck;
    bool mHasVideo;
    uint32_t mHeaderTimescale;
    bool mIsQT;

    Track *mFirstTrack, *mLastTrack;