MPEG4Extractor.cpp revision 5d2f8ba30c24ea597d54468cda01c7ec5f6a0e66
120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/*
220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright (C) 2009 The Android Open Source Project
320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License.
620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at
720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software
1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and
1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License.
1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */
1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#define LOG_TAG "MPEG4Extractor"
1820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/Log.h>
1920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2066326a5ee0869f1ee4d136a477e6effba428b3cbAndreas Huber#include "include/MPEG4Extractor.h"
2189e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber#include "include/SampleTable.h"
227a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang#include "include/ESDS.h"
2389e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber
2420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <arpa/inet.h>
2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <ctype.h>
2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <stdint.h>
2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <stdlib.h>
2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <string.h>
3020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#include <media/stagefright/foundation/ADebug.h>
32a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber#include <media/stagefright/foundation/AMessage.h>
3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/DataSource.h>
3420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBufferGroup.h>
3618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
3720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h>
4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/String8.h>
4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Source : public MediaSource {
4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
4620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Caller retains ownership of both "dataSource" and "sampleTable".
47693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    MPEG4Source(const sp<MetaData> &format,
48693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber                const sp<DataSource> &dataSource,
4948c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                int32_t timeScale,
50693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber                const sp<SampleTable> &sampleTable);
5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t start(MetaData *params = NULL);
5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t stop();
5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual sp<MetaData> getFormat();
5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t read(
5820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            MediaBuffer **buffer, const ReadOptions *options = NULL);
5920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
60693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huberprotected:
61693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    virtual ~MPEG4Source();
62693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber
6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
647b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex mLock;
657b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
6620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mFormat;
67693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<DataSource> mDataSource;
6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t mTimescale;
69693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<SampleTable> mSampleTable;
7020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t mCurrentSampleIndex;
7120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mIsAVC;
736064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    size_t mNALLengthSize;
746064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
7520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mStarted;
7620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBufferGroup *mGroup;
7820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *mBuffer;
8020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
81dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool mWantsNALFragments;
8220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
830024245e134467d120b40099da16c467dc365e76Andreas Huber    uint8_t *mSrcBuffer;
840024245e134467d120b40099da16c467dc365e76Andreas Huber
856064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    size_t parseNALSize(const uint8_t *data) const;
866064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
8720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source(const MPEG4Source &);
8820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source &operator=(const MPEG4Source &);
8920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
9020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This custom data source wraps an existing one and satisfies requests
9250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// falling entirely within a cached range from the cache while forwarding
9350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// all remaining requests to the wrapped datasource.
9450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This is used to cache the full sampletable metadata for a single track,
9550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// possibly wrapping multiple times to cover all tracks, i.e.
9650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// Each MPEG4DataSource caches the sampletable metadata for a single track.
9750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
9850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstruct MPEG4DataSource : public DataSource {
9950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource(const sp<DataSource> &source);
10050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
10150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual status_t initCheck() const;
102c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
103c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    virtual status_t getSize(off64_t *size);
10450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual uint32_t flags();
10550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
106c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    status_t setCachedRange(off64_t offset, size_t size);
10750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
10850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprotected:
10950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual ~MPEG4DataSource();
11050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
11150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprivate:
11250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex mLock;
11350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
11450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    sp<DataSource> mSource;
115c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t mCachedOffset;
11650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    size_t mCachedSize;
11750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    uint8_t *mCache;
11850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
11950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    void clearCache();
12050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
12150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource(const MPEG4DataSource &);
12250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource &operator=(const MPEG4DataSource &);
12350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber};
12450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
12550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source)
12650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    : mSource(source),
12750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCachedOffset(0),
12850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCachedSize(0),
12950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCache(NULL) {
13050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
13150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
13250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::~MPEG4DataSource() {
13350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    clearCache();
13450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
13550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
13650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Hubervoid MPEG4DataSource::clearCache() {
13750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (mCache) {
13850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        free(mCache);
13950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        mCache = NULL;
14050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
14150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
14250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedOffset = 0;
14350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedSize = 0;
14450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
14550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
14650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstatus_t MPEG4DataSource::initCheck() const {
14750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->initCheck();
14850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
14950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
150c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongssize_t MPEG4DataSource::readAt(off64_t offset, void *data, size_t size) {
15150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex::Autolock autoLock(mLock);
15250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
15350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (offset >= mCachedOffset
15450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            && offset + size <= mCachedOffset + mCachedSize) {
15550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        memcpy(data, &mCache[offset - mCachedOffset], size);
15650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return size;
15750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
15850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
15950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->readAt(offset, data, size);
16050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
16150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
162c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4DataSource::getSize(off64_t *size) {
16350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->getSize(size);
16450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
16550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
16650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberuint32_t MPEG4DataSource::flags() {
16750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->flags();
16850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
16950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
170c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4DataSource::setCachedRange(off64_t offset, size_t size) {
17150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex::Autolock autoLock(mLock);
17250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    clearCache();
17450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCache = (uint8_t *)malloc(size);
17650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (mCache == NULL) {
17850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return -ENOMEM;
17950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
18050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedOffset = offset;
18250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedSize = size;
18350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    ssize_t err = mSource->readAt(mCachedOffset, mCache, mCachedSize);
18550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (err < (ssize_t)size) {
18750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        clearCache();
18850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return ERROR_IO;
19050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
19150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return OK;
19350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
19450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber////////////////////////////////////////////////////////////////////////////////
19650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatic void hexdump(const void *_data, size_t size) {
19820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const uint8_t *data = (const uint8_t *)_data;
19920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t offset = 0;
20020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (offset < size) {
20120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf("0x%04x  ", offset);
20220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        size_t n = size - offset;
20420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (n > 16) {
20520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            n = 16;
20620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
20720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < 16; ++i) {
20920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (i == 8) {
21020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(" ");
21120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
21220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (offset + i < size) {
21420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%02x ", data[offset + i]);
21520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
21620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("   ");
21720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
21820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
21920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf(" ");
22120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < n; ++i) {
22320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (isprint(data[offset + i])) {
22420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%c", data[offset + i]);
22520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
22620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(".");
22720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
22820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
22920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf("\n");
23120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        offset += 16;
23320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
23420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
23520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huberstatic const char *FourCC2MIME(uint32_t fourcc) {
23720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch (fourcc) {
23820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
23918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AAC;
24020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
24218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_NB;
24320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
244371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
24518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_WB;
246371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
24720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
24818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_MPEG4;
24920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
25020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
251e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('h', '2', '6', '3'):
252e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('H', '2', '6', '3'):
25318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_H263;
25420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
25520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
25618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_AVC;
25720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
25820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
259dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(!"should not be here.");
26020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
26120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
26220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
264693d271e62a3726689ff68f4505ba49228eb94b2Andreas HuberMPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
26520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mDataSource(source),
266bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber      mInitCheck(NO_INIT),
2677be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber      mHasVideo(false),
26820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mFirstTrack(NULL),
26972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber      mLastTrack(NULL),
270dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mFileMetaData(new MetaData),
271dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mFirstSINF(NULL),
272dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mIsDrm(false) {
27320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
27420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Extractor::~MPEG4Extractor() {
27620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
27720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        Track *next = track->next;
27920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete track;
28120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = next;
28220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
28320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFirstTrack = mLastTrack = NULL;
284dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
285dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    SINF *sinf = mFirstSINF;
286dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (sinf) {
287dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        SINF *next = sinf->next;
288dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        delete sinf->IPMPData;
289dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        delete sinf;
290dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf = next;
291dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
292dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    mFirstSINF = NULL;
29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2957be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Hubersp<MetaData> MPEG4Extractor::getMetaData() {
2967be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    status_t err;
2977be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    if ((err = readMetaData()) != OK) {
29872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return new MetaData;
2997be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    }
3007be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
30172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return mFileMetaData;
3027be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber}
3037be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
304693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersize_t MPEG4Extractor::countTracks() {
30520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
30620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
307693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return 0;
30820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
30920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
310693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    size_t n = 0;
31120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
31220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
313693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        ++n;
31420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
31520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
31620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
317693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    return n;
31820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
31920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3207e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Hubersp<MetaData> MPEG4Extractor::getTrackMetaData(
3217e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        size_t index, uint32_t flags) {
32220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
32320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
32420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return NULL;
32520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
32620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
32820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
32920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
33020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
33120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
33220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
33420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
33520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
33620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
337371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
338371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
339371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
340371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
3417e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    if ((flags & kIncludeExtensiveMetaData)
3427e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            && !track->includes_expensive_metadata) {
3437e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        track->includes_expensive_metadata = true;
3447e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
3457e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        const char *mime;
3467e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        CHECK(track->meta->findCString(kKeyMIMEType, &mime));
3477e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        if (!strncasecmp("video/", mime, 6)) {
3487e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            uint32_t sampleIndex;
3497e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            uint32_t sampleTime;
3507e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK
351c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                    && track->sampleTable->getMetaDataForSample(
352c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                        sampleIndex, NULL /* offset */, NULL /* size */,
353c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                        &sampleTime) == OK) {
3547e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                track->meta->setInt64(
3557e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                        kKeyThumbnailTime,
3567e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                        ((int64_t)sampleTime * 1000000) / track->timescale);
3577e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            }
3587e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        }
3597e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    }
3607e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
36120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return track->meta;
36220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
36320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Extractor::readMetaData() {
365bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    if (mInitCheck != NO_INIT) {
366bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        return mInitCheck;
36720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
36820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
369c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = 0;
37020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
37120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while ((err = parseChunk(&offset, 0)) == OK) {
37220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
3737be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
374bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    if (mInitCheck == OK) {
37572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        if (mHasVideo) {
37672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(kKeyMIMEType, "video/mp4");
37772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else {
37872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
37972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
38072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
3814678a6dc5f09008481524949a9667af5a6190374Andreas Huber        mInitCheck = OK;
382bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    } else {
383bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        mInitCheck = err;
38420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
38520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
386bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    CHECK_NE(err, (status_t)NO_INIT);
387bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    return mInitCheck;
38820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
38920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
390dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wangchar* MPEG4Extractor::getDrmTrackInfo(size_t trackID, int *len) {
391dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mFirstSINF == NULL) {
392dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return NULL;
393dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
394dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
395dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    SINF *sinf = mFirstSINF;
396dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (sinf && (trackID != sinf->trackID)) {
397dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf = sinf->next;
398dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
399dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
400dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (sinf == NULL) {
401dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return NULL;
402dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
403dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
404dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    *len = sinf->len;
405dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return sinf->IPMPData;
406dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
407dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
408dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang// Reads an encoded integer 7 bits at a time until it encounters the high bit clear.
409c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongint32_t readSize(off64_t offset,
410dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        const sp<DataSource> DataSource, uint8_t *numOfBytes) {
411dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint32_t size = 0;
412dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t data;
413dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    bool moreData = true;
414dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    *numOfBytes = 0;
415dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
416dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (moreData) {
417dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (DataSource->readAt(offset, &data, 1) < 1) {
418dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return -1;
419dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
420dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        offset ++;
421dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        moreData = (data >= 128) ? true : false;
422dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        size = (size << 7) | (data & 0x7f); // Take last 7 bits
423dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        (*numOfBytes) ++;
424dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
425dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
426dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return size;
427dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
428dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
429c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseDrmSINF(off64_t *offset, off64_t data_offset) {
430dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t updateIdTag;
431dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
432dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
433dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
434dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset ++;
435dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
436dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (0x01/*OBJECT_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
437dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
438dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
439dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
440dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t numOfBytes;
441dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    int32_t size = readSize(data_offset, mDataSource, &numOfBytes);
442dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size < 0) {
443dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
444dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
445dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    int32_t classSize = size;
446dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset += numOfBytes;
447dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
448dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while(size >= 11 ) {
449dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t descriptorTag;
450dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, &descriptorTag, 1) < 1) {
451dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
452dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
453dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset ++;
454dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
455dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (0x11/*OBJECT_DESCRIPTOR_ID_TAG*/ != descriptorTag) {
456dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
457dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
458dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
459dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t buffer[8];
460dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        //ObjectDescriptorID and ObjectDescriptor url flag
461dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, buffer, 2) < 2) {
462dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
463dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
464dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset += 2;
465dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
466dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if ((buffer[1] >> 5) & 0x0001) { //url flag is set
467dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
468dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
469dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
470dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, buffer, 8) < 8) {
471dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
472dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
473dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset += 8;
474dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
475dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if ((0x0F/*ES_ID_REF_TAG*/ != buffer[1])
476dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                || ( 0x0A/*IPMP_DESCRIPTOR_POINTER_ID_TAG*/ != buffer[5])) {
477dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
478dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
479dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
480dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        SINF *sinf = new SINF;
481dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->trackID = U16_AT(&buffer[3]);
482dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->IPMPDescriptorID = buffer[7];
483dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->next = mFirstSINF;
484dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        mFirstSINF = sinf;
485dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
486dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        size -= (8 + 2 + 1);
487dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
488dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
489dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size != 0) {
490dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
491dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
492dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
493dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
494dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
495dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
496dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset ++;
497dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
498dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if(0x05/*IPMP_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
499dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
500dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
501dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
502dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    size = readSize(data_offset, mDataSource, &numOfBytes);
503dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size < 0) {
504dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
505dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
506dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    classSize = size;
507dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset += numOfBytes;
508dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
509dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (size > 0) {
510dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t tag;
511dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        int32_t dataLen;
512dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, &tag, 1) < 1) {
513dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
514dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
515dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset ++;
516dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
517dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (0x0B/*IPMP_DESCRIPTOR_ID_TAG*/ == tag) {
518dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            uint8_t id;
519dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            dataLen = readSize(data_offset, mDataSource, &numOfBytes);
520dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (dataLen < 0) {
521dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
522dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            } else if (dataLen < 4) {
523dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
524dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
525dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset += numOfBytes;
526dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
527dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (mDataSource->readAt(data_offset, &id, 1) < 1) {
528dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
529dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
530dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset ++;
531dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
532dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            SINF *sinf = mFirstSINF;
533dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            while (sinf && (sinf->IPMPDescriptorID != id)) {
534dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                sinf = sinf->next;
535dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
536dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (sinf == NULL) {
537dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
538dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
539dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            sinf->len = dataLen - 3;
540dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            sinf->IPMPData = new char[sinf->len];
541dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
542dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (mDataSource->readAt(data_offset + 2, sinf->IPMPData, sinf->len) < sinf->len) {
543dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
544dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
545dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset += sinf->len;
546dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
547dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size -= (dataLen + numOfBytes + 1);
548dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
549dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
550dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
551dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size != 0) {
552dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
553dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
554dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
555dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return UNKNOWN_ERROR;  // Return a dummy error.
556dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
557dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
55820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatic void MakeFourCCString(uint32_t x, char *s) {
55920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    s[0] = x >> 24;
56020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    s[1] = (x >> 16) & 0xff;
56120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    s[2] = (x >> 8) & 0xff;
56220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    s[3] = x & 0xff;
56320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    s[4] = '\0';
56420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
56520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
56672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstruct PathAdder {
56772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder(Vector<uint32_t> *path, uint32_t chunkType)
56872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        : mPath(path) {
56972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        mPath->push(chunkType);
57072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
57172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
57272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    ~PathAdder() {
57372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        mPath->pop();
57472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
57572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
57672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberprivate:
57772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    Vector<uint32_t> *mPath;
57872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
57972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder(const PathAdder &);
58072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder &operator=(const PathAdder &);
58172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber};
58272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
58372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic bool underMetaDataPath(const Vector<uint32_t> &path) {
58472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return path.size() >= 5
58572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[0] == FOURCC('m', 'o', 'o', 'v')
58672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[1] == FOURCC('u', 'd', 't', 'a')
58772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[2] == FOURCC('m', 'e', 't', 'a')
58872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[3] == FOURCC('i', 'l', 's', 't');
58972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
59072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
59172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber// Given a time in seconds since Jan 1 1904, produce a human-readable string.
59272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic void convertTimeToDate(int64_t time_1904, String8 *s) {
59372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    time_t time_1970 = time_1904 - (((66 * 365 + 17) * 24) * 3600);
59472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
59572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    char tmp[32];
59672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", gmtime(&time_1970));
59772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
59872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    s->setTo(tmp);
59972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
60072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
601c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
6025d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    ALOGV("entering parseChunk %lld/%d", *offset, depth);
60320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t hdr[2];
60434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
60520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_IO;
60620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
60720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint64_t chunk_size = ntohl(hdr[0]);
60820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t chunk_type = ntohl(hdr[1]);
609c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t data_offset = *offset + 8;
61020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
61120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (chunk_size == 1) {
61234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
61320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_IO;
61420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
61520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        chunk_size = ntoh64(chunk_size);
61620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        data_offset += 8;
61771b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber
61871b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        if (chunk_size < 16) {
61971b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber            // The smallest valid chunk is 16 bytes long in this case.
62071b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber            return ERROR_MALFORMED;
62171b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        }
62271b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber    } else if (chunk_size < 8) {
62371b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        // The smallest valid chunk is 8 bytes long.
62471b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        return ERROR_MALFORMED;
62520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
62620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
62720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    char chunk[5];
62820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MakeFourCCString(chunk_type, chunk);
6295d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    ALOGV("chunk: %s @ %lld", chunk, *offset);
63020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#if 0
63220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static const char kWhitespace[] = "                                        ";
63320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
63420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size);
63520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    char buffer[256];
637ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    size_t n = chunk_size;
638ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    if (n > sizeof(buffer)) {
639ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        n = sizeof(buffer);
640ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    }
641ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    if (mDataSource->readAt(*offset, buffer, n)
642ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber            < (ssize_t)n) {
643ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        return ERROR_IO;
64420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
645ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
646ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    hexdump(buffer, n);
64720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#endif
64820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder autoAdder(&mPath, chunk_type);
65072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
651c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t chunk_data_size = *offset + chunk_size - data_offset;
65220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
65372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (chunk_type != FOURCC('c', 'p', 'r', 't')
654515e855eae78aa495da58356486aaa666cb57fd1James Dong            && chunk_type != FOURCC('c', 'o', 'v', 'r')
65572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            && mPath.size() == 5 && underMetaDataPath(mPath)) {
656c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t stop_offset = *offset + chunk_size;
65772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        *offset = data_offset;
65872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        while (*offset < stop_offset) {
65972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            status_t err = parseChunk(offset, depth + 1);
66072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (err != OK) {
66172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return err;
66272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
66372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
664bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
665bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (*offset != stop_offset) {
666bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
667bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
66872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
66972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return OK;
67072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
67172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
67220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch(chunk_type) {
67320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'v'):
67420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'k'):
67520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'i', 'a'):
67620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'i', 'n', 'f'):
67720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('d', 'i', 'n', 'f'):
67820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'b', 'l'):
67920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'v', 'e', 'x'):
68020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'f'):
68120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'f'):
68220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'f', 'r', 'a'):
68372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('u', 'd', 't', 'a'):
68472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('i', 'l', 's', 't'):
68520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
68650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
6873856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size);
68850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
689b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                if (mDataSource->flags()
690b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                        & (DataSource::kWantsPrefetching
691b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                            | DataSource::kIsCachingDataSource)) {
69250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    sp<MPEG4DataSource> cachedSource =
69350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                        new MPEG4DataSource(mDataSource);
69450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
69550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
69650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                        mDataSource = cachedSource;
69750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    }
69850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                }
6991edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber
7001edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber                mLastTrack->sampleTable = new SampleTable(mDataSource);
70150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            }
70250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
7036f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber            bool isTrack = false;
704bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (chunk_type == FOURCC('t', 'r', 'a', 'k')) {
7056f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                isTrack = true;
7066f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
707bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                Track *track = new Track;
708bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->next = NULL;
709bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                if (mLastTrack) {
710bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    mLastTrack->next = track;
711bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                } else {
712bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    mFirstTrack = track;
713bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                }
714bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                mLastTrack = track;
715bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
716bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->meta = new MetaData;
717bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->includes_expensive_metadata = false;
7186f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                track->skipTrack = false;
719bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->timescale = 0;
720bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->meta->setCString(kKeyMIMEType, "application/octet-stream");
721bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
722bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
723c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
72420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset;
72520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
72620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
72720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
72820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
72920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
73020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
73120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
732bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
733bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
734bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
735bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
7366f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber            if (isTrack) {
7376f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                if (mLastTrack->skipTrack) {
7386f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    Track *cur = mFirstTrack;
7396f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
7406f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    if (cur == mLastTrack) {
7416f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        delete cur;
7426f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        mFirstTrack = mLastTrack = NULL;
7436f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    } else {
7446f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        while (cur && cur->next != mLastTrack) {
7456f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                            cur = cur->next;
7466f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        }
7476f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        cur->next = NULL;
7486f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        delete mLastTrack;
7496f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        mLastTrack = cur;
7506f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    }
7516f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
7526f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    return OK;
7536f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                }
7546f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
755bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                status_t err = verifyTrack(mLastTrack);
756bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
757bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                if (err != OK) {
758bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    return err;
759bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                }
760bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
761bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                mInitCheck = OK;
76220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
763dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                if (!mIsDrm) {
764dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return UNKNOWN_ERROR;  // Return a dummy error.
765dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                } else {
766dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return OK;
767dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
76820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
77020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'k', 'h', 'd'):
77320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
774ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            status_t err;
775ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) {
776ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber                return err;
77720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
77820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
78020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
78120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
78220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
78320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'h', 'd'):
78420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
78520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
78620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
78720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
78820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
78920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t version;
79034769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
79120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, &version, sizeof(version))
79220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(version)) {
79320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
79420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
79520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
796c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t timescale_offset;
79720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
79820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
79920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 16;
80020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else if (version == 0) {
80120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 8;
80220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
80320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
80420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
80520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
80620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t timescale;
80734769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
80820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        timescale_offset, &timescale, sizeof(timescale))
80920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(timescale)) {
81020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
81120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
81220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
81320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->timescale = ntohl(timescale);
81420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
81520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int64_t duration;
81620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
81734769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
81820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration, sizeof(duration))
81920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration)) {
82020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
82120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
82220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = ntoh64(duration);
82320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
82420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                int32_t duration32;
82534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
82620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration32, sizeof(duration32))
82720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration32)) {
82820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
82920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
83020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = ntohl(duration32);
83120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
83248c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mLastTrack->meta->setInt64(
83348c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                    kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
83420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8357a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            uint8_t lang[2];
8367a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            off64_t lang_offset;
8377a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            if (version == 1) {
8387a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                lang_offset = timescale_offset + 4 + 8;
8397a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            } else if (version == 0) {
8407a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                lang_offset = timescale_offset + 4 + 4;
8417a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            } else {
8427a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                return ERROR_IO;
8437a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            }
8447a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
8457a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            if (mDataSource->readAt(lang_offset, &lang, sizeof(lang))
8467a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                    < (ssize_t)sizeof(lang)) {
8477a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                return ERROR_IO;
8487a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            }
8497a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
8507a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // To get the ISO-639-2/T three character language code
8517a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // 1 bit pad followed by 3 5-bits characters. Each character
8527a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // is packed as the difference between its ASCII value and 0x60.
8537a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            char lang_code[4];
8547a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[0] = ((lang[0] >> 2) & 0x1f) + 0x60;
8557a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[1] = ((lang[0] & 0x3) << 3 | (lang[1] >> 5)) + 0x60;
8567a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[2] = (lang[1] & 0x1f) + 0x60;
8577a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[3] = '\0';
8587a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
8597a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            mLastTrack->meta->setCString(
8607a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                    kKeyMediaLanguage, lang_code);
8617a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
86220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
86320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
86420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
86520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
86620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'd'):
86720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
86820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 8) {
86920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
87020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
87120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
87220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8];
873c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size < (off64_t)sizeof(buffer)) {
874bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
875bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
876bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
87734769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
87820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, 8) < 8) {
87920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
88020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
88120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
88220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
88320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
88420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
88520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
88620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
88720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t entry_count = U32_AT(&buffer[4]);
88820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
88920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (entry_count > 1) {
8903b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // For 3GPP timed text, there could be multiple tx3g boxes contain
8913b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // multiple text display formats. These formats will be used to
8923b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // display the timed text.
8933b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                const char *mime;
8943b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
8953b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
8963b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    // For now we only support a single type of media per track.
8973b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    mLastTrack->skipTrack = true;
8983b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    *offset += chunk_size;
8993b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    break;
9003b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                }
90120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
90220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
903c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
90420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + 8;
90520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            for (uint32_t i = 0; i < entry_count; ++i) {
90620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
90720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
90820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
90920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
91020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
911bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
912bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
913bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
914bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
91520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
91620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
91720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
91820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
91920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
920371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
92120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
92220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8 + 20];
92320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
92420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic AudioSampleEntry size.
92520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
92620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
92720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
92834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
92920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
93020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
93120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
93220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
93320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
93420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t num_channels = U16_AT(&buffer[16]);
93520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
93681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint16_t sample_size = U16_AT(&buffer[18]);
93781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
93881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
93918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB,
94081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                            FourCC2MIME(chunk_type))) {
94181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                // AMR NB audio is always mono, 8kHz
94281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                num_channels = 1;
94381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                sample_rate = 8000;
94481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB,
94518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                               FourCC2MIME(chunk_type))) {
94681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                // AMR WB audio is always mono, 16kHz
94720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                num_channels = 1;
94881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                sample_rate = 16000;
94920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
95020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
95181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber#if 0
95281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            printf("*** coding='%s' %d channels, size %d, rate %d\n",
95381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                   chunk, num_channels, sample_size, sample_rate);
95481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber#endif
95520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
95620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
95720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
95820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
95920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
960c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
96120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
96220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
96320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
96420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
96520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
96620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
96720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
968bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
969bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
970bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
971bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
97220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
97320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
97420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
97520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
97620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
977e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('H', '2', '6', '3'):
978e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('h', '2', '6', '3'):
97920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
98020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
9817be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber            mHasVideo = true;
9827be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
98320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[78];
98420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
98520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic VideoSampleEntry size.
98620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
98720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
98820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
98934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
99020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
99120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
99220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
99320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
99420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
99520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t width = U16_AT(&buffer[6 + 18]);
99620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t height = U16_AT(&buffer[6 + 20]);
99720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
998a6256238d9015c42129fe43791968768fe501efaJames Dong            // The video sample is not stand-compliant if it has invalid dimension.
999a6256238d9015c42129fe43791968768fe501efaJames Dong            // Use some default width and height value, and
1000a6256238d9015c42129fe43791968768fe501efaJames Dong            // let the decoder figure out the actual width and height (and thus
1001a6256238d9015c42129fe43791968768fe501efaJames Dong            // be prepared for INFO_FOMRAT_CHANGED event).
1002a6256238d9015c42129fe43791968768fe501efaJames Dong            if (width == 0)  width  = 352;
1003a6256238d9015c42129fe43791968768fe501efaJames Dong            if (height == 0) height = 288;
1004a6256238d9015c42129fe43791968768fe501efaJames Dong
1005134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            // printf("*** coding='%s' width=%d height=%d\n",
1006134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            //        chunk, width, height);
100720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
100820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
100920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyWidth, width);
101020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyHeight, height);
101120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1012c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
101320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
101420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
101520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
101620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
101720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
101820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
101920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1020bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1021bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1022bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1023bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
102420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
102520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
102620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
102720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'c', 'o'):
102820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('c', 'o', '6', '4'):
102920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
103020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
103120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setChunkOffsetParams(
103220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
103320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
103420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
103520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
103620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
103720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
103820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
103920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
104020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
104120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
104220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'c'):
104320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
104420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
104520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleToChunkParams(
104620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
104720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
104820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
104920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
105020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
105120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
105220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
105320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
105420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
105520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
105620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'z'):
105720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'z', '2'):
105820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
105920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
106020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleSizeParams(
106120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
106220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
106320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
106420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
106520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
106620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1067738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            size_t max_size;
106849110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            err = mLastTrack->sampleTable->getMaxSampleSize(&max_size);
106949110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber
107049110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            if (err != OK) {
107149110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber                return err;
107249110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            }
1073738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber
1074738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            // Assume that a given buffer only contains at most 10 fragments,
1075738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            // each fragment originally prefixed with a 2 byte length will
1076738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
1077738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            // and thus will grow by 2 bytes per fragment.
1078738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
107920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
1080113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong
1081113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            // Calculate average frame rate.
1082113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            const char *mime;
1083113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1084113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            if (!strncasecmp("video/", mime, 6)) {
1085113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                size_t nSamples = mLastTrack->sampleTable->countSamples();
1086113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                int64_t durationUs;
1087113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                if (mLastTrack->meta->findInt64(kKeyDuration, &durationUs)) {
1088113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                    if (durationUs > 0) {
1089113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                        int32_t frameRate = (nSamples * 1000000LL +
1090113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                                    (durationUs >> 1)) / durationUs;
1091113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                        mLastTrack->meta->setInt32(kKeyFrameRate, frameRate);
1092113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                    }
1093113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                }
1094113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            }
1095113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong
109620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
109720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
109820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
109920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 't', 's'):
110020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
110120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
110220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setTimeToSampleParams(
110320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
110420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
110520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
110620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
110720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
110820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
110920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
111020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
111120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
111220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11134931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        case FOURCC('c', 't', 't', 's'):
11144931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        {
11154931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            status_t err =
11164931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                mLastTrack->sampleTable->setCompositionTimeToSampleParams(
11174931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                        data_offset, chunk_data_size);
11184931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
11194931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            if (err != OK) {
11204931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                return err;
11214931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            }
11224931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
11234931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            *offset += chunk_size;
11244931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            break;
11254931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        }
11264931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
112720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 's'):
112820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
112920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
113020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSyncSampleParams(
113120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
113220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
113320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
113420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
113520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
113620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
113720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
113820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
113920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
114020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11414948818cb91176df74c972ac27b2f392b5d148bcJames Dong        // @xyz
11424948818cb91176df74c972ac27b2f392b5d148bcJames Dong        case FOURCC('\xA9', 'x', 'y', 'z'):
11434948818cb91176df74c972ac27b2f392b5d148bcJames Dong        {
11444948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Best case the total data length inside "@xyz" box
11454948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // would be 8, for instance "@xyz" + "\x00\x04\x15\xc7" + "0+0/",
11464948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // where "\x00\x04" is the text string length with value = 4,
11474948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // "\0x15\xc7" is the language code = en, and "0+0" is a
11484948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // location (string) value with longitude = 0 and latitude = 0.
11494948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (chunk_data_size < 8) {
11504948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_MALFORMED;
11514948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
11524948818cb91176df74c972ac27b2f392b5d148bcJames Dong
11534948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Worst case the location string length would be 18,
11544948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // for instance +90.0000-180.0000, without the trailing "/" and
11554948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // the string length + language code.
11564948818cb91176df74c972ac27b2f392b5d148bcJames Dong            char buffer[18];
11574948818cb91176df74c972ac27b2f392b5d148bcJames Dong
11584948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Substracting 5 from the data size is because the text string length +
11594948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // language code takes 4 bytes, and the trailing slash "/" takes 1 byte.
11604948818cb91176df74c972ac27b2f392b5d148bcJames Dong            off64_t location_length = chunk_data_size - 5;
11614948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (location_length >= (off64_t) sizeof(buffer)) {
11624948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_MALFORMED;
11634948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
11644948818cb91176df74c972ac27b2f392b5d148bcJames Dong
11654948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (mDataSource->readAt(
11664948818cb91176df74c972ac27b2f392b5d148bcJames Dong                        data_offset + 4, buffer, location_length) < location_length) {
11674948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_IO;
11684948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
11694948818cb91176df74c972ac27b2f392b5d148bcJames Dong
11704948818cb91176df74c972ac27b2f392b5d148bcJames Dong            buffer[location_length] = '\0';
11714948818cb91176df74c972ac27b2f392b5d148bcJames Dong            mFileMetaData->setCString(kKeyLocation, buffer);
11724948818cb91176df74c972ac27b2f392b5d148bcJames Dong            *offset += chunk_size;
11734948818cb91176df74c972ac27b2f392b5d148bcJames Dong            break;
11744948818cb91176df74c972ac27b2f392b5d148bcJames Dong        }
11754948818cb91176df74c972ac27b2f392b5d148bcJames Dong
117620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('e', 's', 'd', 's'):
117720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
117820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
117920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
118120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
118220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[256];
1183c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size > (off64_t)sizeof(buffer)) {
118420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
118520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
118620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
118734769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
118820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
118920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
119020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
119120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
119220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
119320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
119420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
119520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
119620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
119720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
119820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
119920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1200ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            if (mPath.size() >= 2
1201ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
1202ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // Information from the ESDS must be relied on for proper
1203ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // setup of sample rate and channel count for MPEG4 Audio.
1204ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // The generic header appears to only contain generic
1205ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // information...
1206ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1207ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio(
1208ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                        &buffer[4], chunk_data_size - 4);
1209ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1210ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                if (err != OK) {
1211ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    return err;
1212ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                }
1213ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            }
1214ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
121520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
121620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
121720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
121820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
121920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', 'C'):
122020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
122120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            char buffer[256];
1222c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size > (off64_t)sizeof(buffer)) {
122320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
122420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
122520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
122634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
122720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
122820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
122920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
123020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
123120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
123220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    kKeyAVCC, kTypeAVCC, buffer, chunk_data_size);
123320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
123420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
123520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
123620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
123720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1238244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        case FOURCC('d', '2', '6', '3'):
1239244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        {
124017e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            /*
124117e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * d263 contains a fixed 7 bytes part:
124217e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   vendor - 4 bytes
124317e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   version - 1 byte
124417e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   level - 1 byte
124517e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   profile - 1 byte
124617e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * optionally, "d263" box itself may contain a 16-byte
124717e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * bit rate box (bitr)
124817e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   average bit rate - 4 bytes
124917e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   max bit rate - 4 bytes
125017e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             */
125117e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            char buffer[23];
125217e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            if (chunk_data_size != 7 &&
125317e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong                chunk_data_size != 23) {
125429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Incorrect D263 box size %lld", chunk_data_size);
1255244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                return ERROR_MALFORMED;
1256244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            }
1257244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1258244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            if (mDataSource->readAt(
1259244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                    data_offset, buffer, chunk_data_size) < chunk_data_size) {
1260244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                return ERROR_IO;
1261244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            }
1262244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1263244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size);
1264244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1265244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            *offset += chunk_size;
1266244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            break;
1267244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        }
1268244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
126972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'e', 't', 'a'):
127072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
127172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            uint8_t buffer[4];
1272c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size < (off64_t)sizeof(buffer)) {
1273bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1274bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
1275bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
127672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
127772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, buffer, 4) < 4) {
127872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
127972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
128072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
128172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (U32_AT(buffer) != 0) {
128272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                // Should be version 0, flags 0.
1283ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
1284ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // If it's not, let's assume this is one of those
1285ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // apparently malformed chunks that don't have flags
1286ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // and completely different semantics than what's
1287ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // in the MPEG4 specs and skip it.
1288ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                *offset += chunk_size;
1289ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                return OK;
129072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
129172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1292c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
129372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset = data_offset + sizeof(buffer);
129472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            while (*offset < stop_offset) {
129572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                status_t err = parseChunk(offset, depth + 1);
129672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
129772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
129872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
129972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
1300bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1301bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1302bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1303bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
130472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
130572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
130672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
13075d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('m', 'e', 'a', 'n'):
13085d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('n', 'a', 'm', 'e'):
130972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('d', 'a', 't', 'a'):
131072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
131172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mPath.size() == 6 && underMetaDataPath(mPath)) {
131272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                status_t err = parseMetaData(data_offset, chunk_data_size);
131372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
131472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
131572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
131672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
131772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
131872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
131972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset += chunk_size;
132072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
132172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
132272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
132372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'v', 'h', 'd'):
132472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
132572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (chunk_data_size < 12) {
132672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_MALFORMED;
132772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
132872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
132972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            uint8_t header[12];
133072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
133172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, header, sizeof(header))
133272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    < (ssize_t)sizeof(header)) {
133372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
133472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
133572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
133672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            int64_t creationTime;
133772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (header[0] == 1) {
133872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U64_AT(&header[4]);
1339bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (header[0] != 0) {
1340bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
134172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            } else {
134272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U32_AT(&header[4]);
134372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
134472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
134572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            String8 s;
134672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            convertTimeToDate(creationTime, &s);
134772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
134872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(kKeyDate, s.string());
134972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
135072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset += chunk_size;
135172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
135272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
135372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1354dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        case FOURCC('m', 'd', 'a', 't'):
1355dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        {
1356dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (!mIsDrm) {
1357dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                *offset += chunk_size;
1358dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                break;
1359dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
1360dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
1361dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (chunk_size < 8) {
1362dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
1363dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
1364dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
1365dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return parseDrmSINF(offset, data_offset);
1366dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
1367dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
13683b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        case FOURCC('h', 'd', 'l', 'r'):
13693b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        {
13703b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t buffer;
13713b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (mDataSource->readAt(
13723b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                        data_offset + 8, &buffer, 4) < 4) {
13733b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_IO;
13743b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
13753b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
13763b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type = ntohl(buffer);
13773b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            // For the 3GPP file format, the handler-type within the 'hdlr' box
1378e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            // shall be 'text'. We also want to support 'sbtl' handler type
1379e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            // for a practical reason as various MPEG4 containers use it.
1380e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            if (type == FOURCC('t', 'e', 'x', 't') || type == FOURCC('s', 'b', 't', 'l')) {
13813b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
13823b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
13833b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
13843b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            *offset += chunk_size;
13853b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            break;
13863b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        }
13873b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
13887a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        case FOURCC('t', 'x', '3', 'g'):
13897a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        {
13903b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type;
13913b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            const void *data;
13923b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            size_t size = 0;
13933b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (!mLastTrack->meta->findData(
13943b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    kKeyTextFormatData, &type, &data, &size)) {
13953b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                size = 0;
13963b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
13973b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
13983b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint8_t *buffer = new uint8_t[size + chunk_size];
13993b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
14003b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (size > 0) {
14013b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                memcpy(buffer, data, size);
14023b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
14033b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
14043b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size))
14053b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    < chunk_size) {
14063b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                delete[] buffer;
14073b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                buffer = NULL;
14083b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
14093b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_IO;
14103b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
14113b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
14123b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            mLastTrack->meta->setData(
14133b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    kKeyTextFormatData, 0, buffer, size + chunk_size);
14143b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
14153b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            delete[] buffer;
14167a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
14177a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            *offset += chunk_size;
14187a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            break;
14197a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        }
14207a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
1421515e855eae78aa495da58356486aaa666cb57fd1James Dong        case FOURCC('c', 'o', 'v', 'r'):
1422515e855eae78aa495da58356486aaa666cb57fd1James Dong        {
1423515e855eae78aa495da58356486aaa666cb57fd1James Dong            if (mFileMetaData != NULL) {
14243856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("chunk_data_size = %lld and data_offset = %lld",
1425515e855eae78aa495da58356486aaa666cb57fd1James Dong                        chunk_data_size, data_offset);
1426515e855eae78aa495da58356486aaa666cb57fd1James Dong                uint8_t *buffer = new uint8_t[chunk_data_size + 1];
1427515e855eae78aa495da58356486aaa666cb57fd1James Dong                if (mDataSource->readAt(
1428515e855eae78aa495da58356486aaa666cb57fd1James Dong                    data_offset, buffer, chunk_data_size) != (ssize_t)chunk_data_size) {
1429515e855eae78aa495da58356486aaa666cb57fd1James Dong                    delete[] buffer;
1430515e855eae78aa495da58356486aaa666cb57fd1James Dong                    buffer = NULL;
1431515e855eae78aa495da58356486aaa666cb57fd1James Dong
1432515e855eae78aa495da58356486aaa666cb57fd1James Dong                    return ERROR_IO;
1433515e855eae78aa495da58356486aaa666cb57fd1James Dong                }
1434515e855eae78aa495da58356486aaa666cb57fd1James Dong                const int kSkipBytesOfDataBox = 16;
1435515e855eae78aa495da58356486aaa666cb57fd1James Dong                mFileMetaData->setData(
1436515e855eae78aa495da58356486aaa666cb57fd1James Dong                    kKeyAlbumArt, MetaData::TYPE_NONE,
1437515e855eae78aa495da58356486aaa666cb57fd1James Dong                    buffer + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox);
1438515e855eae78aa495da58356486aaa666cb57fd1James Dong            }
1439515e855eae78aa495da58356486aaa666cb57fd1James Dong
1440515e855eae78aa495da58356486aaa666cb57fd1James Dong            *offset += chunk_size;
1441515e855eae78aa495da58356486aaa666cb57fd1James Dong            break;
1442515e855eae78aa495da58356486aaa666cb57fd1James Dong        }
1443515e855eae78aa495da58356486aaa666cb57fd1James Dong
14445d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('-', '-', '-', '-'):
14455d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        {
14465d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentMean.clear();
14475d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentName.clear();
14485d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentData.clear();
14495d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            *offset += chunk_size;
14505d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            break;
14515d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        }
14525d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen
145320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
145420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
145520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
145620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
145720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
145820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
145920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
146020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
146120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
146220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1463ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huberstatus_t MPEG4Extractor::parseTrackHeader(
1464c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t data_offset, off64_t data_size) {
1465ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (data_size < 4) {
1466ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_MALFORMED;
1467ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1468ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1469ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint8_t version;
1470ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (mDataSource->readAt(data_offset, &version, 1) < 1) {
1471ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_IO;
1472ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1473ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1474ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    size_t dynSize = (version == 1) ? 36 : 24;
1475ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1476ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint8_t buffer[36 + 60];
1477ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1478c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    if (data_size != (off64_t)dynSize + 60) {
1479ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_MALFORMED;
1480ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1481ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1482ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (mDataSource->readAt(
1483ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber                data_offset, buffer, data_size) < (ssize_t)data_size) {
1484ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_IO;
1485ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1486ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1487ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint64_t ctime, mtime, duration;
1488ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t id;
1489ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1490ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (version == 1) {
1491ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        ctime = U64_AT(&buffer[4]);
1492ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mtime = U64_AT(&buffer[12]);
1493ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        id = U32_AT(&buffer[20]);
1494ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        duration = U64_AT(&buffer[28]);
1495ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else {
1496ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        CHECK_EQ((unsigned)version, 0u);
1497ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1498ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        ctime = U32_AT(&buffer[4]);
1499ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mtime = U32_AT(&buffer[8]);
1500ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        id = U32_AT(&buffer[12]);
1501ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        duration = U32_AT(&buffer[20]);
1502ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1503ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1504ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    mLastTrack->meta->setInt32(kKeyTrackID, id);
1505ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1506ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    size_t matrixOffset = dynSize + 16;
1507ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a00 = U32_AT(&buffer[matrixOffset]);
1508ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a01 = U32_AT(&buffer[matrixOffset + 4]);
1509ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t dx = U32_AT(&buffer[matrixOffset + 8]);
1510ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a10 = U32_AT(&buffer[matrixOffset + 12]);
1511ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a11 = U32_AT(&buffer[matrixOffset + 16]);
1512ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t dy = U32_AT(&buffer[matrixOffset + 20]);
1513ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1514ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#if 0
1515df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("x' = %.2f * x + %.2f * y + %.2f",
1516ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber         a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f);
1517df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("y' = %.2f * x + %.2f * y + %.2f",
1518ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber         a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f);
1519ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#endif
1520ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1521ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t rotationDegrees;
1522ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1523ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    static const int32_t kFixedOne = 0x10000;
1524ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) {
1525ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        // Identity, no rotation
1526ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 0;
1527ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) {
1528ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 90;
1529ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) {
1530ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 270;
1531ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) {
1532ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 180;
1533ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else {
15345ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("We only support 0,90,180,270 degree rotation matrices");
1535ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 0;
1536ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1537ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1538ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (rotationDegrees != 0) {
1539ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees);
1540ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1541ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1542b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    // Handle presentation display size, which could be different
1543b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    // from the image size indicated by kKeyWidth and kKeyHeight.
1544ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t width = U32_AT(&buffer[dynSize + 52]);
1545ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t height = U32_AT(&buffer[dynSize + 56]);
1546b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    mLastTrack->meta->setInt32(kKeyDisplayWidth, width >> 16);
1547b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    mLastTrack->meta->setInt32(kKeyDisplayHeight, height >> 16);
1548ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1549ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    return OK;
1550ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber}
1551ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1552c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseMetaData(off64_t offset, size_t size) {
155372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (size < 4) {
155472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_MALFORMED;
155572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
155672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
155772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint8_t *buffer = new uint8_t[size + 1];
155872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (mDataSource->readAt(
155972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                offset, buffer, size) != (ssize_t)size) {
156072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        delete[] buffer;
156172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        buffer = NULL;
156272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
156372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_IO;
156472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
156572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
156672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t flags = U32_AT(buffer);
156772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
156872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t metadataKey = 0;
15695d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    char chunk[5];
15705d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    MakeFourCCString(mPath[4], chunk);
15715d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    ALOGV("meta: %s @ %lld", chunk, offset);
157272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    switch (mPath[4]) {
157372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'a', 'l', 'b'):
157472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
157572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbum;
157672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
157772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
157872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'A', 'R', 'T'):
157972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
158072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyArtist;
158172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
158272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
158366ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        case FOURCC('a', 'A', 'R', 'T'):
158466ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        {
158566ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            metadataKey = kKeyAlbumArtist;
158666ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            break;
158766ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        }
158872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'd', 'a', 'y'):
158972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
159072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyYear;
159172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
159272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
159372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'n', 'a', 'm'):
159472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
159572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyTitle;
159672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
159772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
159872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'w', 'r', 't'):
159972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
160072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyWriter;
160172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
160272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
160372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('c', 'o', 'v', 'r'):
160472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
160572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbumArt;
160672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
160772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
160872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('g', 'n', 'r', 'e'):
160972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
161072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyGenre;
161172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
161272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
161326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC(0xa9, 'g', 'e', 'n'):
161426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
161526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            metadataKey = kKeyGenre;
161626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
161726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
161811f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        case FOURCC('c', 'p', 'i', 'l'):
161911f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        {
162011f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            if (size == 9 && flags == 21) {
162111f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                char tmp[16];
162211f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                sprintf(tmp, "%d",
162311f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                        (int)buffer[size - 1]);
162411f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen
162511f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                mFileMetaData->setCString(kKeyCompilation, tmp);
162611f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            }
162711f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            break;
162811f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        }
162972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('t', 'r', 'k', 'n'):
163072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
163172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (size == 16 && flags == 0) {
163272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char tmp[16];
163372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                sprintf(tmp, "%d/%d",
163472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        (int)buffer[size - 5], (int)buffer[size - 3]);
163572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
163672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
163772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
163872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
163972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
164026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC('d', 'i', 's', 'k'):
164126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
164226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            if (size == 14 && flags == 0) {
164326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                char tmp[16];
164426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                sprintf(tmp, "%d/%d",
164526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                        (int)buffer[size - 3], (int)buffer[size - 1]);
164626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
164726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(kKeyDiscNumber, tmp);
164826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            }
164926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
165026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
16515d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('-', '-', '-', '-'):
16525d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        {
16535d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            buffer[size] = '\0';
16545d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            switch (mPath[5]) {
16555d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('m', 'e', 'a', 'n'):
16565d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentMean.setTo((const char *)buffer + 4);
16575d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
16585d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('n', 'a', 'm', 'e'):
16595d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentName.setTo((const char *)buffer + 4);
16605d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
16615d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('d', 'a', 't', 'a'):
16625d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentData.setTo((const char *)buffer + 8);
16635d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
16645d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            }
16655d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            if (mLastCommentMean == "com.apple.iTunes"
16665d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    && mLastCommentName == "iTunSMPB"
16675d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    && mLastCommentData.length() != 0) {
16685d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                int32_t delay, padding;
16695d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                if (sscanf(mLastCommentData,
16705d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                           " %*x %x %x %*x", &delay, &padding) == 2) {
16715d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
16725d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastTrack->meta->setInt32(kKeyEncoderPadding, padding);
16735d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                }
16745d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentMean.clear();
16755d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentName.clear();
16765d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentData.clear();
16775d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            }
16785d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            break;
16795d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        }
168026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
168172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        default:
168272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
168372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
168472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
168572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (size >= 8 && metadataKey) {
168672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        if (metadataKey == kKeyAlbumArt) {
168772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setData(
168872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    kKeyAlbumArt, MetaData::TYPE_NONE,
168972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    buffer + 8, size - 8);
169072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else if (metadataKey == kKeyGenre) {
169172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (flags == 0) {
169226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // uint8_t genre code, iTunes genre codes are
169326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // the standard id3 codes, except they start
169426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // at 1 instead of 0 (e.g. Pop is 14, not 13)
169526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // We use standard id3 numbering, so subtract 1.
169626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                int genrecode = (int)buffer[size - 1];
169726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                genrecode--;
169826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                if (genrecode < 0) {
169926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                    genrecode = 255; // reserved for 'unknown genre'
170026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                }
170172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char genre[10];
170226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                sprintf(genre, "%d", genrecode);
170372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
170472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(metadataKey, genre);
170526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            } else if (flags == 1) {
170626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // custom genre string
170726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                buffer[size] = '\0';
170826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
170926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(
171026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                        metadataKey, (const char *)buffer + 8);
171172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
171272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else {
171372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            buffer[size] = '\0';
171472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
171572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(
171672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    metadataKey, (const char *)buffer + 8);
171772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
171872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
171972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
172072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    delete[] buffer;
172172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    buffer = NULL;
172272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
172372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return OK;
172472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
172572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1726693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
172720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
172820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
1729693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return NULL;
173020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
173120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
173220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
173320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
173420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
1735693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber            return NULL;
173620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
173720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
173820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
173920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
174020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
174120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1742371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
1743371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
1744371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
1745371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
1746693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    return new MPEG4Source(
174748c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            track->meta, mDataSource, track->timescale, track->sampleTable);
174820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
174920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1750bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber// static
1751bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) {
1752bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const char *mime;
1753bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    CHECK(track->meta->findCString(kKeyMIMEType, &mime));
1754bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1755bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    uint32_t type;
1756bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const void *data;
1757bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    size_t size;
1758bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
1759bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyAVCC, &type, &data, &size)
1760bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeAVCC) {
1761bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
1762bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
1763bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
1764bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
1765bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyESDS, &type, &data, &size)
1766bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeESDS) {
1767bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
1768bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
1769bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    }
1770bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1771169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber    if (!track->sampleTable->isValid()) {
1772169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        // Make sure we have all the metadata we need.
1773169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        return ERROR_MALFORMED;
1774169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber    }
1775169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber
1776bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    return OK;
1777bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber}
1778bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1779ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
1780ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        const void *esds_data, size_t esds_size) {
1781ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    ESDS esds(esds_data, esds_size);
178281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
178381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    uint8_t objectTypeIndication;
178481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
178581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return ERROR_MALFORMED;
178681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
178781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
178881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (objectTypeIndication == 0xe1) {
178981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        // This isn't MPEG4 audio at all, it's QCELP 14k...
179081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
179181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return OK;
179281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
179381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
1794633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong    if (objectTypeIndication  == 0x6b) {
1795633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // The media subtype is MP3 audio
1796633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // Our software MP3 audio decoder may not be able to handle
1797633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // packetized MP3 audio; for now, lets just return ERROR_UNSUPPORTED
179829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("MP3 track in MP4/3GPP file is not supported");
1799633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        return ERROR_UNSUPPORTED;
1800633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong    }
1801633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong
1802ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    const uint8_t *csd;
1803ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    size_t csd_size;
1804ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (esds.getCodecSpecificInfo(
1805ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                (const void **)&csd, &csd_size) != OK) {
1806ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
1807ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
1808ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1809ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#if 0
1810ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    printf("ESD of size %d\n", csd_size);
1811ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    hexdump(csd, csd_size);
1812ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#endif
1813ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1814a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    if (csd_size == 0) {
1815a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // There's no further information, i.e. no codec specific data
1816a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // Let's assume that the information provided in the mpeg4 headers
1817a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // is accurate and hope for the best.
1818a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
1819a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        return OK;
1820a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    }
1821a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
1822ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (csd_size < 2) {
1823ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
1824ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
1825ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1826ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    uint32_t objectType = csd[0] >> 3;
1827ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1828ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (objectType == 31) {
1829ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_UNSUPPORTED;
1830ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
1831ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1832ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    uint32_t freqIndex = (csd[0] & 7) << 1 | (csd[1] >> 7);
1833ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t sampleRate = 0;
1834ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t numChannels = 0;
1835ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (freqIndex == 15) {
1836ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        if (csd_size < 5) {
1837ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            return ERROR_MALFORMED;
1838ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
1839ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1840ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        sampleRate = (csd[1] & 0x7f) << 17
1841ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                        | csd[2] << 9
1842ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                        | csd[3] << 1
1843ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                        | (csd[4] >> 7);
1844ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1845ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        numChannels = (csd[4] >> 3) & 15;
1846ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    } else {
18473c3ddfa39635a2d39f4ee7c966fb9403fe1ec9d8Andreas Huber        static uint32_t kSamplingRate[] = {
18483c3ddfa39635a2d39f4ee7c966fb9403fe1ec9d8Andreas Huber            96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
18493c3ddfa39635a2d39f4ee7c966fb9403fe1ec9d8Andreas Huber            16000, 12000, 11025, 8000, 7350
18503c3ddfa39635a2d39f4ee7c966fb9403fe1ec9d8Andreas Huber        };
1851ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1852ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        if (freqIndex == 13 || freqIndex == 14) {
1853ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            return ERROR_MALFORMED;
1854ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
1855ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1856ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        sampleRate = kSamplingRate[freqIndex];
1857ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        numChannels = (csd[1] >> 3) & 15;
1858ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
1859ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1860ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (numChannels == 0) {
1861ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_UNSUPPORTED;
1862ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
1863ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1864ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevSampleRate;
1865ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
1866ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1867ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevSampleRate != sampleRate) {
18683856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("mpeg4 audio sample rate different from previous setting. "
1869ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevSampleRate, sampleRate);
1870ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
1871ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1872ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
1873ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1874ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevChannelCount;
1875ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
1876ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1877ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevChannelCount != numChannels) {
18783856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("mpeg4 audio channel count different from previous setting. "
1879ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevChannelCount, numChannels);
1880ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
1881ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1882ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
1883ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1884ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    return OK;
1885ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber}
1886ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
188720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
188820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
188920111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::MPEG4Source(
189020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        const sp<MetaData> &format,
1891693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &dataSource,
189248c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        int32_t timeScale,
1893693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<SampleTable> &sampleTable)
189420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mFormat(format),
189520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDataSource(dataSource),
189648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber      mTimescale(timeScale),
189720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSampleTable(sampleTable),
189820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCurrentSampleIndex(0),
189920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mIsAVC(false),
19006064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber      mNALLengthSize(0),
190120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mStarted(false),
190220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mGroup(NULL),
190320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mBuffer(NULL),
1904dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber      mWantsNALFragments(false),
19050024245e134467d120b40099da16c467dc365e76Andreas Huber      mSrcBuffer(NULL) {
190620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
190720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mFormat->findCString(kKeyMIMEType, &mime);
1908dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(success);
190920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
191018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber    mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
19116064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
19126064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    if (mIsAVC) {
19136064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        uint32_t type;
19146064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const void *data;
19156064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t size;
19166064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(format->findData(kKeyAVCC, &type, &data, &size));
19176064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
19186064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const uint8_t *ptr = (const uint8_t *)data;
19196064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
19206064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(size >= 7);
1921ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
19226064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
19236064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        // The number of bytes used to encode the length of a NAL unit.
19246064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        mNALLengthSize = 1 + (ptr[4] & 3);
19256064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
192620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
192720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
192820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::~MPEG4Source() {
192920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mStarted) {
193020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        stop();
193120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
193220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
193320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
193420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::start(MetaData *params) {
19357b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
19367b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
1937dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(!mStarted);
193820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
193920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t val;
1940dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (params && params->findInt32(kKeyWantsNALFragments, &val)
194120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        && val != 0) {
1942dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = true;
194320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    } else {
1944dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = false;
194520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
194620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
194720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = new MediaBufferGroup;
194820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1949738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    int32_t max_size;
1950738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
195120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1952738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    mGroup->add_buffer(new MediaBuffer(max_size));
19530024245e134467d120b40099da16c467dc365e76Andreas Huber
19540024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = new uint8_t[max_size];
195520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
195620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = true;
195720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
195820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
195920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
196020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
196120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::stop() {
19627b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
19637b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
1964dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
196520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
196620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mBuffer != NULL) {
196720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->release();
196820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
196920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
197020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
19710024245e134467d120b40099da16c467dc365e76Andreas Huber    delete[] mSrcBuffer;
19720024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = NULL;
19730024245e134467d120b40099da16c467dc365e76Andreas Huber
197420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    delete mGroup;
197520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = NULL;
197620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
197720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = false;
197820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mCurrentSampleIndex = 0;
197920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
198020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
198120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
198220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
198320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> MPEG4Source::getFormat() {
19847b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
19857b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
198620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return mFormat;
198720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
198820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
19896064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const {
19906064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    switch (mNALLengthSize) {
19916064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 1:
19926064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return *data;
19936064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 2:
19946064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U16_AT(data);
19956064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 3:
19966064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return ((size_t)data[0] << 16) | U16_AT(&data[1]);
19976064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 4:
19986064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U32_AT(data);
19996064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
20006064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
20016064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // This cannot happen, mNALLengthSize springs to life by adding 1 to
20026064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // a 2-bit integer.
20036064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    CHECK(!"Should not be here.");
20046064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
20056064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    return 0;
20066064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber}
20076064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
200820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::read(
200920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
20107b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
20117b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
2012dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
201320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
201420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *out = NULL;
201520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2016abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    int64_t targetSampleTimeUs = -1;
2017abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
201820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t seekTimeUs;
2019abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
2020abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
2021abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t findFlags = 0;
2022abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        switch (mode) {
2023abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_PREVIOUS_SYNC:
2024abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagBefore;
2025abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
2026abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_NEXT_SYNC:
2027abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagAfter;
2028abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
2029abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST_SYNC:
2030abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST:
2031abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagClosest;
2032abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
2033abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            default:
2034abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                CHECK(!"Should not be here.");
2035abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
2036abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
2037abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
203820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        uint32_t sampleIndex;
2039abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        status_t err = mSampleTable->findSampleAtTime(
204020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                seekTimeUs * mTimescale / 1000000,
2041abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                &sampleIndex, findFlags);
2042abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
2043abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
2044abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // We found the closest sample already, now we want the sync
2045abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // sample preceding it (or the sample itself of course), even
2046abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // if the subsequent sync sample is closer.
2047abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            findFlags = SampleTable::kFlagBefore;
2048abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
2049abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
2050abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleIndex;
2051abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (err == OK) {
2052abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            err = mSampleTable->findSyncSampleNear(
2053abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    sampleIndex, &syncSampleIndex, findFlags);
2054abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
205520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2056788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        uint32_t sampleTime;
2057788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        if (err == OK) {
2058788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber            err = mSampleTable->getMetaDataForSample(
2059788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber                    sampleIndex, NULL, NULL, &sampleTime);
2060788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        }
2061788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber
206220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (err != OK) {
20635295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            if (err == ERROR_OUT_OF_RANGE) {
20645295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // An attempt to seek past the end of the stream would
20655295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // normally cause this ERROR_OUT_OF_RANGE error. Propagating
20665295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // this all the way to the MediaPlayer would cause abnormal
20675295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // termination. Legacy behaviour appears to be to behave as if
20685295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // we had seeked to the end of stream, ending normally.
20695295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                err = ERROR_END_OF_STREAM;
20705295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            }
207120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return err;
207220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
207320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2074abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
2075abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
2076abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
2077abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
2078abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#if 0
2079abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleTime;
2080abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
2081abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    syncSampleIndex, NULL, NULL, &syncSampleTime));
2082abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
2083df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("seek to time %lld us => sample at time %lld us, "
2084abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             "sync sample at time %lld us",
2085abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             seekTimeUs,
2086abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             sampleTime * 1000000ll / mTimescale,
2087abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             syncSampleTime * 1000000ll / mTimescale);
2088abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#endif
2089abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
2090abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        mCurrentSampleIndex = syncSampleIndex;
209120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mBuffer != NULL) {
209220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
209320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
209420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
209520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
209620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // fall through
209720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
209820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2099c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset;
21000024245e134467d120b40099da16c467dc365e76Andreas Huber    size_t size;
21014678a6dc5f09008481524949a9667af5a6190374Andreas Huber    uint32_t cts;
21028bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    bool isSyncSample;
2103dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool newBuffer = false;
2104dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (mBuffer == NULL) {
2105dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        newBuffer = true;
210620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2107c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        status_t err =
2108c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber            mSampleTable->getMetaDataForSample(
21094678a6dc5f09008481524949a9667af5a6190374Andreas Huber                    mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample);
211020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2111dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
2112dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
2113dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
2114dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
2115dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        err = mGroup->acquire_buffer(&mBuffer);
2116c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
2117dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
2118ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            CHECK(mBuffer == NULL);
2119dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
2120dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
21210024245e134467d120b40099da16c467dc365e76Andreas Huber    }
212220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2123dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (!mIsAVC || mWantsNALFragments) {
2124dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (newBuffer) {
2125dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ssize_t num_bytes_read =
212634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
2127dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
2128dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            if (num_bytes_read < (ssize_t)size) {
2129dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer->release();
2130dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer = NULL;
2131dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
2132dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                return ERROR_IO;
2133dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            }
2134dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
21357b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber            CHECK(mBuffer != NULL);
2136dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->set_range(0, size);
2137dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->meta_data()->clear();
213848c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mBuffer->meta_data()->setInt64(
21394678a6dc5f09008481524949a9667af5a6190374Andreas Huber                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
2140abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
2141abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            if (targetSampleTimeUs >= 0) {
2142abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                mBuffer->meta_data()->setInt64(
2143abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                        kKeyTargetTime, targetSampleTimeUs);
2144abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            }
2145abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
21468bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            if (isSyncSample) {
21478bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
21488bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            }
21498bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
2150dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ++mCurrentSampleIndex;
2151dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
2152dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
2153dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (!mIsAVC) {
2154dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            *out = mBuffer;
2155dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
2156dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
2157dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return OK;
2158dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
2159dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
2160dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Each NAL unit is split up into its constituent fragments and
2161dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // each one of them returned in its own buffer.
2162dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
21636064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(mBuffer->range_length() >= mNALLengthSize);
2164dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
2165dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        const uint8_t *src =
2166dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
2167dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
21686064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t nal_size = parseNALSize(src);
2169e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
217029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("incomplete NAL unit.");
2171e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
2172e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer->release();
2173e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer = NULL;
2174e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
2175e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            return ERROR_MALFORMED;
2176e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        }
2177dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
2178dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        MediaBuffer *clone = mBuffer->clone();
21797b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(clone != NULL);
21806064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
2181dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
21827b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(mBuffer != NULL);
2183dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mBuffer->set_range(
21846064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_offset() + mNALLengthSize + nal_size,
21856064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_length() - mNALLengthSize - nal_size);
2186dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
2187dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (mBuffer->range_length() == 0) {
2188dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->release();
2189dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
2190dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
2191dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
2192dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        *out = clone;
2193dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
2194dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        return OK;
2195dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    } else {
2196dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Whole NAL units are returned but each fragment is prefixed by
2197dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // the start code (0x00 00 00 01).
2198dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        ssize_t num_bytes_read = 0;
2199dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        int32_t drm = 0;
2200dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
2201dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (usesDRM) {
2202dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            num_bytes_read =
2203dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
2204dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
2205dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
2206dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
220720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
220820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (num_bytes_read < (ssize_t)size) {
220920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
221020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
221120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2212dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return ERROR_IO;
221320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
221420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2215dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (usesDRM) {
2216dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK(mBuffer != NULL);
2217dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            mBuffer->set_range(0, size);
22186064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
2219dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
2220dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            uint8_t *dstData = (uint8_t *)mBuffer->data();
2221dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size_t srcOffset = 0;
2222dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size_t dstOffset = 0;
2223e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
2224dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            while (srcOffset < size) {
222534fe252c89e33572d01fea981b58d7b115e76164James Dong                bool isMalFormed = (srcOffset + mNALLengthSize > size);
222634fe252c89e33572d01fea981b58d7b115e76164James Dong                size_t nalLength = 0;
222734fe252c89e33572d01fea981b58d7b115e76164James Dong                if (!isMalFormed) {
222834fe252c89e33572d01fea981b58d7b115e76164James Dong                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
222934fe252c89e33572d01fea981b58d7b115e76164James Dong                    srcOffset += mNALLengthSize;
223034fe252c89e33572d01fea981b58d7b115e76164James Dong                    isMalFormed = srcOffset + nalLength > size;
223134fe252c89e33572d01fea981b58d7b115e76164James Dong                }
2232e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
223334fe252c89e33572d01fea981b58d7b115e76164James Dong                if (isMalFormed) {
223429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                    ALOGE("Video is malformed");
2235dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    mBuffer->release();
2236dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    mBuffer = NULL;
2237dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return ERROR_MALFORMED;
2238dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
2239dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
2240dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                if (nalLength == 0) {
2241dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    continue;
2242dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
2243dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
2244dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                CHECK(dstOffset + 4 <= mBuffer->size());
2245dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
2246dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
2247dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
2248dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
2249dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 1;
2250dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
2251dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                srcOffset += nalLength;
2252dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstOffset += nalLength;
2253dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
2254dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK_EQ(srcOffset, size);
2255dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK(mBuffer != NULL);
2256dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            mBuffer->set_range(0, dstOffset);
2257dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
2258dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
225920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->meta_data()->clear();
226048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        mBuffer->meta_data()->setInt64(
22614678a6dc5f09008481524949a9667af5a6190374Andreas Huber                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
2262abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
2263abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (targetSampleTimeUs >= 0) {
2264abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            mBuffer->meta_data()->setInt64(
2265abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    kKeyTargetTime, targetSampleTimeUs);
2266abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
2267abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
22688bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        if (isSyncSample) {
22698bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
22708bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        }
22718bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
227220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        ++mCurrentSampleIndex;
227320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
227420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        *out = mBuffer;
227520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
227620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
227720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
227820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
227920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
228020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2281bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas HuberMPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix(
2282bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        const char *mimePrefix) {
2283bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    for (Track *track = mFirstTrack; track != NULL; track = track->next) {
2284bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        const char *mime;
2285bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        if (track->meta != NULL
2286bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                && track->meta->findCString(kKeyMIMEType, &mime)
2287bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) {
2288bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber            return track;
2289bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        }
2290bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    }
2291bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber
2292bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    return NULL;
2293bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber}
2294bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber
22951b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool LegacySniffMPEG4(
2296693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
229720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[8];
229820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
229934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    ssize_t n = source->readAt(4, header, sizeof(header));
230020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (n < (ssize_t)sizeof(header)) {
230120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return false;
230220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
230320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
230420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
2305b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8)
2306b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8)
23070dba73763a04d39faf999dcc5ef12af3c99535a7Andreas Huber        || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
2308ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
2309983b449a27b5fa91eca82ede5204b4341899be62Andreas Huber        || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
231018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
23115a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        *confidence = 0.4;
231220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
231320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return true;
231420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
231520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
231620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return false;
231720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
231820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23191b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool isCompatibleBrand(uint32_t fourcc) {
23201b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    static const uint32_t kCompatibleBrands[] = {
23211b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', 'm'),
23221b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', '2'),
23231b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('a', 'v', 'c', '1'),
23241b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('3', 'g', 'p', '4'),
23251b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '1'),
23261b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '2'),
23274cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong
23284cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        // Won't promise that the following file types can be played.
23294cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        // Just give these file types a chance.
23304cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        FOURCC('q', 't', ' ', ' '),  // Apple's QuickTime
23314cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        FOURCC('M', 'S', 'N', 'V'),  // Sony's PSP
233258fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber
233358fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber        FOURCC('3', 'g', '2', 'a'),  // 3GPP2
233458fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber        FOURCC('3', 'g', '2', 'b'),
23351b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    };
23361b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
23371b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    for (size_t i = 0;
23381b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]);
23391b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         ++i) {
23401b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        if (kCompatibleBrands[i] == fourcc) {
23411b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            return true;
23421b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
23431b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
23441b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
23451b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
23461b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
23471b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
23481b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// Attempt to actually parse the 'ftyp' atom and determine if a suitable
23491b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// compatible brand is present.
2350a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// Also try to identify where this file's metadata ends
2351a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// (end of the 'moov' atom) and report it to the caller as part of
2352a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// the metadata.
23531b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool BetterSniffMPEG4(
2354a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
2355a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        sp<AMessage> *meta) {
2356a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    // We scan up to 128 bytes to identify this file as an MP4.
2357a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    static const off64_t kMaxScanOffset = 128ll;
23581b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
2359a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    off64_t offset = 0ll;
2360a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    bool foundGoodFileType = false;
2361a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    off64_t moovAtomEndOffset = -1ll;
2362a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    bool done = false;
23631b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
2364a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    while (!done && offset < kMaxScanOffset) {
2365a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint32_t hdr[2];
2366a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        if (source->readAt(offset, hdr, 8) < 8) {
2367a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            return false;
2368a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        }
2369a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
2370a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint64_t chunkSize = ntohl(hdr[0]);
2371a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint32_t chunkType = ntohl(hdr[1]);
2372a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        off64_t chunkDataOffset = offset + 8;
2373a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
2374a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        if (chunkSize == 1) {
2375a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            if (source->readAt(offset + 8, &chunkSize, 8) < 8) {
23761b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                return false;
23771b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
23781b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
2379a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            chunkSize = ntoh64(chunkSize);
2380a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            chunkDataOffset += 8;
2381a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
2382a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            if (chunkSize < 16) {
2383a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                // The smallest valid chunk is 16 bytes long in this case.
2384a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                return false;
2385a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            }
2386a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        } else if (chunkSize < 8) {
2387a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            // The smallest valid chunk is 8 bytes long.
2388a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            return false;
2389a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        }
2390a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
2391a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        off64_t chunkDataSize = offset + chunkSize - chunkDataOffset;
2392a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
2393a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        switch (chunkType) {
2394a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            case FOURCC('f', 't', 'y', 'p'):
2395a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            {
2396a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                if (chunkDataSize < 8) {
2397a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    return false;
2398a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
2399a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
2400a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4;
2401a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
2402a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (i == 1) {
2403a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        // Skip this index, it refers to the minorVersion,
2404a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        // not a brand.
2405a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        continue;
2406a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
2407a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
2408a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    uint32_t brand;
2409a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (source->readAt(
2410a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                                chunkDataOffset + 4 * i, &brand, 4) < 4) {
2411a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        return false;
2412a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
2413a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
2414a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    brand = ntohl(brand);
2415a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
2416a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (isCompatibleBrand(brand)) {
2417a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        foundGoodFileType = true;
2418a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        break;
2419a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
2420a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
2421a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
2422a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                if (!foundGoodFileType) {
2423a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    return false;
2424a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
2425a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
24261b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                break;
24271b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
2428a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
2429a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            case FOURCC('m', 'o', 'o', 'v'):
2430a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            {
2431a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                moovAtomEndOffset = offset + chunkSize;
2432a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
2433a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                done = true;
2434a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                break;
2435a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            }
2436a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
2437a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            default:
2438a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                break;
24391b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
2440a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
2441a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        offset += chunkSize;
24421b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
24431b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
2444a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (!foundGoodFileType) {
24451b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return false;
24461b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
24471b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
24481b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
24495a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber    *confidence = 0.4f;
24501b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
2451a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (moovAtomEndOffset >= 0) {
2452a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        *meta = new AMessage;
2453a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        (*meta)->setInt64("meta-data-size", moovAtomEndOffset);
2454a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
2455456caf3f5f0af673dc120c17c23635f40d8f5ac2Andreas Huber        ALOGV("found metadata size: %lld", moovAtomEndOffset);
2456a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    }
2457a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
24581b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return true;
24591b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
24601b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
24611b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberbool SniffMPEG4(
24625a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
2463a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        sp<AMessage> *meta) {
2464a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (BetterSniffMPEG4(source, mimeType, confidence, meta)) {
24651b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
24661b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
24671b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
24681b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    if (LegacySniffMPEG4(source, mimeType, confidence)) {
24695ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Identified supported mpeg4 through LegacySniffMPEG4.");
24701b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
24711b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
24721b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
24731b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
24741b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
24751b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
247620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
2477