MPEG4Extractor.cpp revision b9d3038ec950665639e26acd51329ebc800e780d
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"
2289e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber
2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <arpa/inet.h>
2420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <ctype.h>
2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <stdint.h>
2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <stdlib.h>
2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <string.h>
2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/DataSource.h>
31ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#include "include/ESDS.h"
3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBufferGroup.h>
34dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber#include <media/stagefright/MediaDebug.h>
3518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
3620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
3720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h>
3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/String8.h>
4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Source : public MediaSource {
4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Caller retains ownership of both "dataSource" and "sampleTable".
46693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    MPEG4Source(const sp<MetaData> &format,
47693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber                const sp<DataSource> &dataSource,
4848c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                int32_t timeScale,
49693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber                const sp<SampleTable> &sampleTable);
5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t start(MetaData *params = NULL);
5220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t stop();
5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual sp<MetaData> getFormat();
5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t read(
5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            MediaBuffer **buffer, const ReadOptions *options = NULL);
5820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
59693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huberprotected:
60693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    virtual ~MPEG4Source();
61693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber
6220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
637b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex mLock;
647b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mFormat;
66693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<DataSource> mDataSource;
6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t mTimescale;
68693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<SampleTable> mSampleTable;
6920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t mCurrentSampleIndex;
7020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mIsAVC;
726064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    size_t mNALLengthSize;
736064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
7420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mStarted;
7520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBufferGroup *mGroup;
7720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *mBuffer;
7920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
80dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool mWantsNALFragments;
8120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
820024245e134467d120b40099da16c467dc365e76Andreas Huber    uint8_t *mSrcBuffer;
830024245e134467d120b40099da16c467dc365e76Andreas Huber
846064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    size_t parseNALSize(const uint8_t *data) const;
856064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
8620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source(const MPEG4Source &);
8720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source &operator=(const MPEG4Source &);
8820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
8920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This custom data source wraps an existing one and satisfies requests
9150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// falling entirely within a cached range from the cache while forwarding
9250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// all remaining requests to the wrapped datasource.
9350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This is used to cache the full sampletable metadata for a single track,
9450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// possibly wrapping multiple times to cover all tracks, i.e.
9550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// Each MPEG4DataSource caches the sampletable metadata for a single track.
9650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
9750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstruct MPEG4DataSource : public DataSource {
9850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource(const sp<DataSource> &source);
9950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
10050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual status_t initCheck() const;
10150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual ssize_t readAt(off_t offset, void *data, size_t size);
10250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual status_t getSize(off_t *size);
10350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual uint32_t flags();
10450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
10550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    status_t setCachedRange(off_t offset, size_t size);
10650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
10750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprotected:
10850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual ~MPEG4DataSource();
10950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
11050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprivate:
11150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex mLock;
11250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
11350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    sp<DataSource> mSource;
11450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    off_t mCachedOffset;
11550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    size_t mCachedSize;
11650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    uint8_t *mCache;
11750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
11850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    void clearCache();
11950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
12050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource(const MPEG4DataSource &);
12150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource &operator=(const MPEG4DataSource &);
12250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber};
12350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
12450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source)
12550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    : mSource(source),
12650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCachedOffset(0),
12750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCachedSize(0),
12850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCache(NULL) {
12950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
13050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
13150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::~MPEG4DataSource() {
13250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    clearCache();
13350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
13450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
13550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Hubervoid MPEG4DataSource::clearCache() {
13650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (mCache) {
13750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        free(mCache);
13850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        mCache = NULL;
13950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
14050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
14150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedOffset = 0;
14250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedSize = 0;
14350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
14450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
14550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstatus_t MPEG4DataSource::initCheck() const {
14650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->initCheck();
14750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
14850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
14950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberssize_t MPEG4DataSource::readAt(off_t offset, void *data, size_t size) {
15050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex::Autolock autoLock(mLock);
15150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
15250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (offset >= mCachedOffset
15350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            && offset + size <= mCachedOffset + mCachedSize) {
15450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        memcpy(data, &mCache[offset - mCachedOffset], size);
15550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return size;
15650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
15750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
15850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->readAt(offset, data, size);
15950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
16050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
16150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstatus_t MPEG4DataSource::getSize(off_t *size) {
16250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->getSize(size);
16350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
16450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
16550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberuint32_t MPEG4DataSource::flags() {
16650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->flags();
16750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
16850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
16950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstatus_t MPEG4DataSource::setCachedRange(off_t offset, size_t size) {
17050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex::Autolock autoLock(mLock);
17150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    clearCache();
17350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCache = (uint8_t *)malloc(size);
17550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (mCache == NULL) {
17750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return -ENOMEM;
17850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
17950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedOffset = offset;
18150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedSize = size;
18250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    ssize_t err = mSource->readAt(mCachedOffset, mCache, mCachedSize);
18450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (err < (ssize_t)size) {
18650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        clearCache();
18750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return ERROR_IO;
18950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
19050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return OK;
19250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
19350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber////////////////////////////////////////////////////////////////////////////////
19550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatic void hexdump(const void *_data, size_t size) {
19720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const uint8_t *data = (const uint8_t *)_data;
19820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t offset = 0;
19920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (offset < size) {
20020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf("0x%04x  ", offset);
20120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        size_t n = size - offset;
20320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (n > 16) {
20420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            n = 16;
20520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
20620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < 16; ++i) {
20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (i == 8) {
20920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(" ");
21020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
21120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (offset + i < size) {
21320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%02x ", data[offset + i]);
21420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
21520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("   ");
21620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
21720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
21820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
21920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf(" ");
22020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < n; ++i) {
22220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (isprint(data[offset + i])) {
22320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%c", data[offset + i]);
22420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
22520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(".");
22620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
22720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
22820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf("\n");
23020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        offset += 16;
23220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
23320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
23420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huberstatic const char *FourCC2MIME(uint32_t fourcc) {
23620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch (fourcc) {
23720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
23818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AAC;
23920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
24118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_NB;
24220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
243371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
24418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_WB;
245371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
24620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
24718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_MPEG4;
24820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
25018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_H263;
25120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
25220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
25318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_AVC;
25420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
25520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
256dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(!"should not be here.");
25720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
25820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
25920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
26020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
261693d271e62a3726689ff68f4505ba49228eb94b2Andreas HuberMPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
26220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mDataSource(source),
26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mHaveMetadata(false),
2647be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber      mHasVideo(false),
26520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mFirstTrack(NULL),
26672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber      mLastTrack(NULL),
26772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber      mFileMetaData(new MetaData) {
26820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
26920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Extractor::~MPEG4Extractor() {
27120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
27220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
27320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        Track *next = track->next;
27420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete track;
27620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = next;
27720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFirstTrack = mLastTrack = NULL;
27920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
28020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2817be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Hubersp<MetaData> MPEG4Extractor::getMetaData() {
2827be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    status_t err;
2837be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    if ((err = readMetaData()) != OK) {
28472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return new MetaData;
2857be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    }
2867be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
28772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return mFileMetaData;
2887be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber}
2897be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
290693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersize_t MPEG4Extractor::countTracks() {
29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
293693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return 0;
29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
296693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    size_t n = 0;
29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
29820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
299693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        ++n;
30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
30120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
30220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
303693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    return n;
30420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
30520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3067e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Hubersp<MetaData> MPEG4Extractor::getTrackMetaData(
3077e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        size_t index, uint32_t flags) {
30820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
30920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
31020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return NULL;
31120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
31220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
31420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
31520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
31620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
31720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
31820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
32020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
32120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
32220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
323371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
324371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
325371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
326371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
3277e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    if ((flags & kIncludeExtensiveMetaData)
3287e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            && !track->includes_expensive_metadata) {
3297e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        track->includes_expensive_metadata = true;
3307e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
3317e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        const char *mime;
3327e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        CHECK(track->meta->findCString(kKeyMIMEType, &mime));
3337e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        if (!strncasecmp("video/", mime, 6)) {
3347e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            uint32_t sampleIndex;
3357e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            uint32_t sampleTime;
3367e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK
337c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                    && track->sampleTable->getMetaDataForSample(
338c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                        sampleIndex, NULL /* offset */, NULL /* size */,
339c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                        &sampleTime) == OK) {
3407e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                track->meta->setInt64(
3417e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                        kKeyThumbnailTime,
3427e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                        ((int64_t)sampleTime * 1000000) / track->timescale);
3437e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            }
3447e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        }
3457e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    }
3467e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
34720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return track->meta;
34820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
34920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Extractor::readMetaData() {
35120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mHaveMetadata) {
35220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
35320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
35420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t offset = 0;
35620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while ((err = parseChunk(&offset, 0)) == OK) {
35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
3597be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
36020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mHaveMetadata) {
36172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        if (mHasVideo) {
36272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(kKeyMIMEType, "video/mp4");
36372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else {
36472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
36572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
36672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
36720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
36820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
36920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return err;
37120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
37220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatic void MakeFourCCString(uint32_t x, char *s) {
37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    s[0] = x >> 24;
37520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    s[1] = (x >> 16) & 0xff;
37620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    s[2] = (x >> 8) & 0xff;
37720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    s[3] = x & 0xff;
37820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    s[4] = '\0';
37920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
38020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
38172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstruct PathAdder {
38272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder(Vector<uint32_t> *path, uint32_t chunkType)
38372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        : mPath(path) {
38472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        mPath->push(chunkType);
38572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
38672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
38772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    ~PathAdder() {
38872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        mPath->pop();
38972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
39072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
39172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberprivate:
39272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    Vector<uint32_t> *mPath;
39372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
39472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder(const PathAdder &);
39572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder &operator=(const PathAdder &);
39672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber};
39772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
39872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic bool underMetaDataPath(const Vector<uint32_t> &path) {
39972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return path.size() >= 5
40072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[0] == FOURCC('m', 'o', 'o', 'v')
40172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[1] == FOURCC('u', 'd', 't', 'a')
40272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[2] == FOURCC('m', 'e', 't', 'a')
40372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[3] == FOURCC('i', 'l', 's', 't');
40472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
40572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
40672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber// Given a time in seconds since Jan 1 1904, produce a human-readable string.
40772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic void convertTimeToDate(int64_t time_1904, String8 *s) {
40872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    time_t time_1970 = time_1904 - (((66 * 365 + 17) * 24) * 3600);
40972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
41072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    char tmp[32];
41172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", gmtime(&time_1970));
41272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
41372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    s->setTo(tmp);
41472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
41572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
41620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
41720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t hdr[2];
41834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
41920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_IO;
42020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
42120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint64_t chunk_size = ntohl(hdr[0]);
42220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t chunk_type = ntohl(hdr[1]);
42320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t data_offset = *offset + 8;
42420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
42520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (chunk_size == 1) {
42634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
42720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_IO;
42820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
42920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        chunk_size = ntoh64(chunk_size);
43020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        data_offset += 8;
43171b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber
43271b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        if (chunk_size < 16) {
43371b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber            // The smallest valid chunk is 16 bytes long in this case.
43471b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber            return ERROR_MALFORMED;
43571b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        }
43671b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber    } else if (chunk_size < 8) {
43771b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        // The smallest valid chunk is 8 bytes long.
43871b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        return ERROR_MALFORMED;
43920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
44020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
44120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    char chunk[5];
44220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MakeFourCCString(chunk_type, chunk);
44320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
44420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#if 0
44520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static const char kWhitespace[] = "                                        ";
44620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
44720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size);
44820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
44920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    char buffer[256];
450ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    size_t n = chunk_size;
451ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    if (n > sizeof(buffer)) {
452ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        n = sizeof(buffer);
453ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    }
454ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    if (mDataSource->readAt(*offset, buffer, n)
455ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber            < (ssize_t)n) {
456ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        return ERROR_IO;
45720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
458ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
459ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    hexdump(buffer, n);
46020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#endif
46120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
46272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder autoAdder(&mPath, chunk_type);
46372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
46420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    off_t chunk_data_size = *offset + chunk_size - data_offset;
46520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
46672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (chunk_type != FOURCC('c', 'p', 'r', 't')
46772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            && mPath.size() == 5 && underMetaDataPath(mPath)) {
46872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        off_t stop_offset = *offset + chunk_size;
46972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        *offset = data_offset;
47072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        while (*offset < stop_offset) {
47172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            status_t err = parseChunk(offset, depth + 1);
47272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (err != OK) {
47372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return err;
47472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
47572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
476bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
477bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (*offset != stop_offset) {
478bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
479bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
48072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
48172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return OK;
48272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
48372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
48420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch(chunk_type) {
48520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'v'):
48620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'k'):
48720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'i', 'a'):
48820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'i', 'n', 'f'):
48920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('d', 'i', 'n', 'f'):
49020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'b', 'l'):
49120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'v', 'e', 'x'):
49220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'f'):
49320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'f'):
49420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'f', 'r', 'a'):
49572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('u', 'd', 't', 'a'):
49672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('i', 'l', 's', 't'):
49720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
49850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
49950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                LOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size);
50050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
501b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                if (mDataSource->flags()
502b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                        & (DataSource::kWantsPrefetching
503b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                            | DataSource::kIsCachingDataSource)) {
50450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    sp<MPEG4DataSource> cachedSource =
50550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                        new MPEG4DataSource(mDataSource);
50650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
50750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
50850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                        mDataSource = cachedSource;
50950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    }
51050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                }
5111edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber
5121edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber                mLastTrack->sampleTable = new SampleTable(mDataSource);
51350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            }
51450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
5156f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber            bool isTrack = false;
516bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (chunk_type == FOURCC('t', 'r', 'a', 'k')) {
5176f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                isTrack = true;
5186f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
519bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                Track *track = new Track;
520bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->next = NULL;
521bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                if (mLastTrack) {
522bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    mLastTrack->next = track;
523bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                } else {
524bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    mFirstTrack = track;
525bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                }
526bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                mLastTrack = track;
527bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
528bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->meta = new MetaData;
529bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->includes_expensive_metadata = false;
5306f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                track->skipTrack = false;
531bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->timescale = 0;
532bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->meta->setCString(kKeyMIMEType, "application/octet-stream");
533bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
534bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
53520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            off_t stop_offset = *offset + chunk_size;
53620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset;
53720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
53820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
53920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
54020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
54120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
54220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
54320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
544bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
545bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
546bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
547bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
5486f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber            if (isTrack) {
5496f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                if (mLastTrack->skipTrack) {
5506f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    Track *cur = mFirstTrack;
5516f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
5526f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    if (cur == mLastTrack) {
5536f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        delete cur;
5546f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        mFirstTrack = mLastTrack = NULL;
5556f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    } else {
5566f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        while (cur && cur->next != mLastTrack) {
5576f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                            cur = cur->next;
5586f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        }
5596f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        cur->next = NULL;
5606f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        delete mLastTrack;
5616f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        mLastTrack = cur;
5626f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    }
5636f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
5646f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    return OK;
5656f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                }
5666f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
567bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                status_t err = verifyTrack(mLastTrack);
568bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
569bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                if (err != OK) {
570bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    return err;
571bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                }
572bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
57320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mHaveMetadata = true;
57420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
57520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return UNKNOWN_ERROR;  // Return a dummy error.
57620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
57720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
57820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
57920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
58020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'k', 'h', 'd'):
58120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
582bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (chunk_data_size < 4) {
583bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
584bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
58520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
58620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t version;
58734769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(data_offset, &version, 1) < 1) {
58820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
58920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
59020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint64_t ctime, mtime, duration;
59220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int32_t id;
59320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t width, height;
59420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
59520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
59620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (chunk_data_size != 36 + 60) {
59720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_MALFORMED;
59820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
59920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
60020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                uint8_t buffer[36 + 60];
60134769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
60220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
60320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
60420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
60520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
60620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                ctime = U64_AT(&buffer[4]);
60720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mtime = U64_AT(&buffer[12]);
60820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                id = U32_AT(&buffer[20]);
60920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = U64_AT(&buffer[28]);
61020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                width = U32_AT(&buffer[88]);
61120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                height = U32_AT(&buffer[92]);
61220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else if (version == 0) {
61320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (chunk_data_size != 24 + 60) {
61420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_MALFORMED;
61520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
61620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
61720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                uint8_t buffer[24 + 60];
61834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
61920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
62020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
62120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
62220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                ctime = U32_AT(&buffer[4]);
62320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mtime = U32_AT(&buffer[8]);
62420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                id = U32_AT(&buffer[12]);
62520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = U32_AT(&buffer[20]);
62620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                width = U32_AT(&buffer[76]);
62720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                height = U32_AT(&buffer[80]);
62820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
62920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
63120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
63220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
63320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'h', 'd'):
63520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
63620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
63720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
63820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
63920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t version;
64134769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
64220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, &version, sizeof(version))
64320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(version)) {
64420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
64520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
64620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            off_t timescale_offset;
64820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
65020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 16;
65120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else if (version == 0) {
65220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 8;
65320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
65420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
65520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
65620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
65720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t timescale;
65834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
65920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        timescale_offset, &timescale, sizeof(timescale))
66020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(timescale)) {
66120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
66220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
66320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->timescale = ntohl(timescale);
66520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int64_t duration;
66720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
66834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
66920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration, sizeof(duration))
67020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration)) {
67120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
67220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
67320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = ntoh64(duration);
67420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
67520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                int32_t duration32;
67634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
67720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration32, sizeof(duration32))
67820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration32)) {
67920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
68020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
68120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = ntohl(duration32);
68220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
68348c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mLastTrack->meta->setInt64(
68448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                    kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
68520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
68620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
68720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
68820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
68920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
69020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'd'):
69120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
69220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 8) {
69320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
69420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
69520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
69620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8];
697bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (chunk_data_size < (off_t)sizeof(buffer)) {
698bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
699bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
700bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
70134769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
70220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, 8) < 8) {
70320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
70420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
70520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
70620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
70720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
70820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
70920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
71020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
71120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t entry_count = U32_AT(&buffer[4]);
71220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
71320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (entry_count > 1) {
71420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // For now we only support a single type of media per track.
7156f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
7166f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                mLastTrack->skipTrack = true;
7176f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                *offset += chunk_size;
7186f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                break;
71920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
72020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
72120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            off_t stop_offset = *offset + chunk_size;
72220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + 8;
72320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            for (uint32_t i = 0; i < entry_count; ++i) {
72420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
72520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
72620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
72720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
72820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
729bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
730bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
731bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
732bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
73320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
73420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
73520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
73620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
73720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
738371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
74020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8 + 20];
74120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic AudioSampleEntry size.
74320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
74420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
74520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
74634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
74720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
74820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
74920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
75020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
75120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
75220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t num_channels = U16_AT(&buffer[16]);
75320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
75481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint16_t sample_size = U16_AT(&buffer[18]);
75581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
75681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
75718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB,
75881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                            FourCC2MIME(chunk_type))) {
75981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                // AMR NB audio is always mono, 8kHz
76081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                num_channels = 1;
76181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                sample_rate = 8000;
76281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB,
76318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                               FourCC2MIME(chunk_type))) {
76481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                // AMR WB audio is always mono, 16kHz
76520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                num_channels = 1;
76681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                sample_rate = 16000;
76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
76820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
76981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber#if 0
77081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            printf("*** coding='%s' %d channels, size %d, rate %d\n",
77181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                   chunk, num_channels, sample_size, sample_rate);
77281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber#endif
77320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
77720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            off_t stop_offset = *offset + chunk_size;
77920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
78020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
78120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
78220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
78320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
78420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
78520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
786bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
787bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
788bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
789bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
79020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
79120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
79220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
79320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
79420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
79520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
79620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
7977be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber            mHasVideo = true;
7987be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
79920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[78];
80020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
80120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic VideoSampleEntry size.
80220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
80320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
80420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
80534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
80620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
80720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
80820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
80920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
81020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
81120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t width = U16_AT(&buffer[6 + 18]);
81220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t height = U16_AT(&buffer[6 + 20]);
81320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
814134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            // printf("*** coding='%s' width=%d height=%d\n",
815134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            //        chunk, width, height);
81620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
81720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
81820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyWidth, width);
81920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyHeight, height);
82020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
82120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            off_t stop_offset = *offset + chunk_size;
82220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
82320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
82420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
82520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
82620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
82720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
82820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
829bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
830bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
831bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
832bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
83320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
83420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
83520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
83620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'c', 'o'):
83720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('c', 'o', '6', '4'):
83820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
83920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
84020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setChunkOffsetParams(
84120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
84220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
84320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
84420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
84520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
84620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
84720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
84820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
84920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
85020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
85120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'c'):
85220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
85320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
85420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleToChunkParams(
85520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
85620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
85720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
85820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
85920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
86020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
86120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
86220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
86320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
86420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
86520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'z'):
86620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'z', '2'):
86720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
86820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
86920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleSizeParams(
87020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
87120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
87220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
87320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
87420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
87520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
876738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            size_t max_size;
87749110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            err = mLastTrack->sampleTable->getMaxSampleSize(&max_size);
87849110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber
87949110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            if (err != OK) {
88049110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber                return err;
88149110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            }
882738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber
883738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            // Assume that a given buffer only contains at most 10 fragments,
884738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            // each fragment originally prefixed with a 2 byte length will
885738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
886738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            // and thus will grow by 2 bytes per fragment.
887738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
888738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber
88920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
89020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
89120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
89220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
89320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 't', 's'):
89420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
89520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
89620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setTimeToSampleParams(
89720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
89820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
89920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
90020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
90120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
90220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
90320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
90420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
90520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
90620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
90720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 's'):
90820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
90920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
91020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSyncSampleParams(
91120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
91220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
91320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
91420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
91520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
91620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
91720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
91820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
91920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
92020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
92120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('e', 's', 'd', 's'):
92220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
92320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
92420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
92520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
92620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
92720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[256];
92820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size > (off_t)sizeof(buffer)) {
92920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
93020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
93120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
93234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
93320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
93420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
93520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
93620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
93720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
93820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
93920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
94020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
94120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
94220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
94320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
94420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
945ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            if (mPath.size() >= 2
946ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
947ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // Information from the ESDS must be relied on for proper
948ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // setup of sample rate and channel count for MPEG4 Audio.
949ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // The generic header appears to only contain generic
950ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // information...
951ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
952ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio(
953ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                        &buffer[4], chunk_data_size - 4);
954ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
955ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                if (err != OK) {
956ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    return err;
957ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                }
958ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            }
959ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
96020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
96120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
96220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
96320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
96420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', 'C'):
96520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
96620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            char buffer[256];
96720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size > (off_t)sizeof(buffer)) {
96820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
96920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
97020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
97134769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
97220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
97320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
97420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
97520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
97620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
97720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    kKeyAVCC, kTypeAVCC, buffer, chunk_data_size);
97820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
97920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
98020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
98120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
98220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
98372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'e', 't', 'a'):
98472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
98572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            uint8_t buffer[4];
986bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (chunk_data_size < (off_t)sizeof(buffer)) {
987bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
988bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
989bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
99072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
99172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, buffer, 4) < 4) {
99272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
99372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
99472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
99572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (U32_AT(buffer) != 0) {
99672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                // Should be version 0, flags 0.
997ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
998ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // If it's not, let's assume this is one of those
999ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // apparently malformed chunks that don't have flags
1000ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // and completely different semantics than what's
1001ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // in the MPEG4 specs and skip it.
1002ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                *offset += chunk_size;
1003ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                return OK;
100472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
100572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
100672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            off_t stop_offset = *offset + chunk_size;
100772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset = data_offset + sizeof(buffer);
100872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            while (*offset < stop_offset) {
100972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                status_t err = parseChunk(offset, depth + 1);
101072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
101172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
101272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
101372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
1014bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1015bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1016bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1017bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
101872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
101972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
102072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
102172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('d', 'a', 't', 'a'):
102272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
102372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mPath.size() == 6 && underMetaDataPath(mPath)) {
102472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                status_t err = parseMetaData(data_offset, chunk_data_size);
102572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
102672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
102772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
102872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
102972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
103072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
103172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset += chunk_size;
103272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
103372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
103472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
103572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'v', 'h', 'd'):
103672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
103772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (chunk_data_size < 12) {
103872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_MALFORMED;
103972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
104072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
104172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            uint8_t header[12];
104272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
104372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, header, sizeof(header))
104472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    < (ssize_t)sizeof(header)) {
104572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
104672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
104772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
104872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            int64_t creationTime;
104972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (header[0] == 1) {
105072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U64_AT(&header[4]);
1051bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (header[0] != 0) {
1052bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
105372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            } else {
105472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U32_AT(&header[4]);
105572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
105672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
105772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            String8 s;
105872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            convertTimeToDate(creationTime, &s);
105972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
106072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(kKeyDate, s.string());
106172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
106272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset += chunk_size;
106372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
106472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
106572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
106620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
106720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
106820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
106920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
107020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
107120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
107220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
107320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
107420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
107520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
107672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatus_t MPEG4Extractor::parseMetaData(off_t offset, size_t size) {
107772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (size < 4) {
107872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_MALFORMED;
107972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
108072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
108172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint8_t *buffer = new uint8_t[size + 1];
108272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (mDataSource->readAt(
108372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                offset, buffer, size) != (ssize_t)size) {
108472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        delete[] buffer;
108572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        buffer = NULL;
108672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
108772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_IO;
108872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
108972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
109072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t flags = U32_AT(buffer);
109172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
109272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t metadataKey = 0;
109372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    switch (mPath[4]) {
109472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'a', 'l', 'b'):
109572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
109672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbum;
109772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
109872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
109972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'A', 'R', 'T'):
110072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
110172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyArtist;
110272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
110372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
110466ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        case FOURCC('a', 'A', 'R', 'T'):
110566ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        {
110666ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            metadataKey = kKeyAlbumArtist;
110766ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            break;
110866ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        }
110972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'd', 'a', 'y'):
111072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
111172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyYear;
111272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
111372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
111472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'n', 'a', 'm'):
111572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
111672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyTitle;
111772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
111872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
111972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'w', 'r', 't'):
112072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
112172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyWriter;
112272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
112372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
112472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('c', 'o', 'v', 'r'):
112572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
112672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbumArt;
112772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
112872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
112972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('g', 'n', 'r', 'e'):
113072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
113172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyGenre;
113272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
113372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
113426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC(0xa9, 'g', 'e', 'n'):
113526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
113626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            metadataKey = kKeyGenre;
113726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
113826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
113972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('t', 'r', 'k', 'n'):
114072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
114172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (size == 16 && flags == 0) {
114272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char tmp[16];
114372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                sprintf(tmp, "%d/%d",
114472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        (int)buffer[size - 5], (int)buffer[size - 3]);
114572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
114672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
114772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
114872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
114972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
115026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC('d', 'i', 's', 'k'):
115126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
115226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            if (size == 14 && flags == 0) {
115326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                char tmp[16];
115426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                sprintf(tmp, "%d/%d",
115526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                        (int)buffer[size - 3], (int)buffer[size - 1]);
115626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
115726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(kKeyDiscNumber, tmp);
115826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            }
115926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
116026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
116126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
116272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        default:
116372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
116472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
116572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
116672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (size >= 8 && metadataKey) {
116772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        if (metadataKey == kKeyAlbumArt) {
116872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setData(
116972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    kKeyAlbumArt, MetaData::TYPE_NONE,
117072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    buffer + 8, size - 8);
117172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else if (metadataKey == kKeyGenre) {
117272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (flags == 0) {
117326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // uint8_t genre code, iTunes genre codes are
117426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // the standard id3 codes, except they start
117526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // at 1 instead of 0 (e.g. Pop is 14, not 13)
117626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // We use standard id3 numbering, so subtract 1.
117726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                int genrecode = (int)buffer[size - 1];
117826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                genrecode--;
117926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                if (genrecode < 0) {
118026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                    genrecode = 255; // reserved for 'unknown genre'
118126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                }
118272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char genre[10];
118326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                sprintf(genre, "%d", genrecode);
118472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
118572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(metadataKey, genre);
118626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            } else if (flags == 1) {
118726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // custom genre string
118826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                buffer[size] = '\0';
118926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
119026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(
119126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                        metadataKey, (const char *)buffer + 8);
119272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
119372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else {
119472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            buffer[size] = '\0';
119572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
119672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(
119772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    metadataKey, (const char *)buffer + 8);
119872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
119972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
120072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
120172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    delete[] buffer;
120272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    buffer = NULL;
120372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
120472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return OK;
120572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
120672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1207693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
120820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
120920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
1210693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return NULL;
121120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
121220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
121320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
121420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
121520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
1216693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber            return NULL;
121720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
121820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
121920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
122020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
122120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
122220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1223371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
1224371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
1225371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
1226371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
1227693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    return new MPEG4Source(
122848c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            track->meta, mDataSource, track->timescale, track->sampleTable);
122920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
123020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1231bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber// static
1232bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) {
1233bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const char *mime;
1234bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    CHECK(track->meta->findCString(kKeyMIMEType, &mime));
1235bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1236bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    uint32_t type;
1237bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const void *data;
1238bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    size_t size;
1239bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
1240bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyAVCC, &type, &data, &size)
1241bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeAVCC) {
1242bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
1243bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
1244bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
1245bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
1246bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyESDS, &type, &data, &size)
1247bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeESDS) {
1248bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
1249bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
1250bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    }
1251bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1252bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    return OK;
1253bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber}
1254bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1255ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
1256ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        const void *esds_data, size_t esds_size) {
1257ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    ESDS esds(esds_data, esds_size);
125881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
125981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    uint8_t objectTypeIndication;
126081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
126181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return ERROR_MALFORMED;
126281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
126381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
126481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (objectTypeIndication == 0xe1) {
126581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        // This isn't MPEG4 audio at all, it's QCELP 14k...
126681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
126781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return OK;
126881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
126981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
1270ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    const uint8_t *csd;
1271ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    size_t csd_size;
1272ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (esds.getCodecSpecificInfo(
1273ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                (const void **)&csd, &csd_size) != OK) {
1274ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
1275ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
1276ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1277ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#if 0
1278ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    printf("ESD of size %d\n", csd_size);
1279ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    hexdump(csd, csd_size);
1280ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#endif
1281ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1282a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    if (csd_size == 0) {
1283a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // There's no further information, i.e. no codec specific data
1284a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // Let's assume that the information provided in the mpeg4 headers
1285a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // is accurate and hope for the best.
1286a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
1287a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        return OK;
1288a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    }
1289a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
1290ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (csd_size < 2) {
1291ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
1292ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
1293ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1294ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    uint32_t objectType = csd[0] >> 3;
1295ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1296ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (objectType == 31) {
1297ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_UNSUPPORTED;
1298ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
1299ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1300ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    uint32_t freqIndex = (csd[0] & 7) << 1 | (csd[1] >> 7);
1301ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t sampleRate = 0;
1302ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t numChannels = 0;
1303ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (freqIndex == 15) {
1304ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        if (csd_size < 5) {
1305ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            return ERROR_MALFORMED;
1306ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
1307ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1308ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        sampleRate = (csd[1] & 0x7f) << 17
1309ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                        | csd[2] << 9
1310ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                        | csd[3] << 1
1311ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                        | (csd[4] >> 7);
1312ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1313ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        numChannels = (csd[4] >> 3) & 15;
1314ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    } else {
13153c3ddfa39635a2d39f4ee7c966fb9403fe1ec9d8Andreas Huber        static uint32_t kSamplingRate[] = {
13163c3ddfa39635a2d39f4ee7c966fb9403fe1ec9d8Andreas Huber            96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
13173c3ddfa39635a2d39f4ee7c966fb9403fe1ec9d8Andreas Huber            16000, 12000, 11025, 8000, 7350
13183c3ddfa39635a2d39f4ee7c966fb9403fe1ec9d8Andreas Huber        };
1319ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1320ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        if (freqIndex == 13 || freqIndex == 14) {
1321ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            return ERROR_MALFORMED;
1322ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
1323ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1324ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        sampleRate = kSamplingRate[freqIndex];
1325ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        numChannels = (csd[1] >> 3) & 15;
1326ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
1327ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1328ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (numChannels == 0) {
1329ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_UNSUPPORTED;
1330ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
1331ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1332ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevSampleRate;
1333ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
1334ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1335ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevSampleRate != sampleRate) {
1336ec9dd59902c8beea4ba6a842f3a843d46150d949Andreas Huber        LOGV("mpeg4 audio sample rate different from previous setting. "
1337ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevSampleRate, sampleRate);
1338ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
1339ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1340ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
1341ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1342ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevChannelCount;
1343ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
1344ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1345ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevChannelCount != numChannels) {
1346ec9dd59902c8beea4ba6a842f3a843d46150d949Andreas Huber        LOGV("mpeg4 audio channel count different from previous setting. "
1347ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevChannelCount, numChannels);
1348ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
1349ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1350ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
1351ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1352ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    return OK;
1353ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber}
1354ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
135520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
135720111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::MPEG4Source(
135820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        const sp<MetaData> &format,
1359693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &dataSource,
136048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        int32_t timeScale,
1361693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<SampleTable> &sampleTable)
136220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mFormat(format),
136320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDataSource(dataSource),
136448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber      mTimescale(timeScale),
136520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSampleTable(sampleTable),
136620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCurrentSampleIndex(0),
136720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mIsAVC(false),
13686064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber      mNALLengthSize(0),
136920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mStarted(false),
137020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mGroup(NULL),
137120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mBuffer(NULL),
1372dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber      mWantsNALFragments(false),
13730024245e134467d120b40099da16c467dc365e76Andreas Huber      mSrcBuffer(NULL) {
137420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
137520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mFormat->findCString(kKeyMIMEType, &mime);
1376dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(success);
137720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
137818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber    mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
13796064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
13806064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    if (mIsAVC) {
13816064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        uint32_t type;
13826064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const void *data;
13836064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t size;
13846064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(format->findData(kKeyAVCC, &type, &data, &size));
13856064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
13866064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const uint8_t *ptr = (const uint8_t *)data;
13876064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
13886064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(size >= 7);
13896064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK_EQ(ptr[0], 1);  // configurationVersion == 1
13906064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
13916064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        // The number of bytes used to encode the length of a NAL unit.
13926064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        mNALLengthSize = 1 + (ptr[4] & 3);
13936064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
139420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
139520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
139620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::~MPEG4Source() {
139720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mStarted) {
139820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        stop();
139920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
140020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
140120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
140220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::start(MetaData *params) {
14037b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
14047b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
1405dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(!mStarted);
140620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
140720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t val;
1408dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (params && params->findInt32(kKeyWantsNALFragments, &val)
140920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        && val != 0) {
1410dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = true;
141120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    } else {
1412dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = false;
141320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
141420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
141520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = new MediaBufferGroup;
141620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1417738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    int32_t max_size;
1418738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
141920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1420738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    mGroup->add_buffer(new MediaBuffer(max_size));
14210024245e134467d120b40099da16c467dc365e76Andreas Huber
14220024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = new uint8_t[max_size];
142320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
142420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = true;
142520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
142620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
142720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
142820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
142920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::stop() {
14307b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
14317b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
1432dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
143320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
143420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mBuffer != NULL) {
143520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->release();
143620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
143720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
143820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14390024245e134467d120b40099da16c467dc365e76Andreas Huber    delete[] mSrcBuffer;
14400024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = NULL;
14410024245e134467d120b40099da16c467dc365e76Andreas Huber
144220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    delete mGroup;
144320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = NULL;
144420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
144520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = false;
144620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mCurrentSampleIndex = 0;
144720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
144820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
144920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
145020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
145120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> MPEG4Source::getFormat() {
14527b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
14537b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
145420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return mFormat;
145520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
145620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14576064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const {
14586064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    switch (mNALLengthSize) {
14596064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 1:
14606064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return *data;
14616064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 2:
14626064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U16_AT(data);
14636064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 3:
14646064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return ((size_t)data[0] << 16) | U16_AT(&data[1]);
14656064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 4:
14666064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U32_AT(data);
14676064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
14686064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
14696064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // This cannot happen, mNALLengthSize springs to life by adding 1 to
14706064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // a 2-bit integer.
14716064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    CHECK(!"Should not be here.");
14726064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
14736064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    return 0;
14746064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber}
14756064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
147620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::read(
147720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
14787b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
14797b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
1480dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
148120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
148220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *out = NULL;
148320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1484abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    int64_t targetSampleTimeUs = -1;
1485abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
148620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t seekTimeUs;
1487abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
1488abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
1489abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t findFlags = 0;
1490abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        switch (mode) {
1491abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_PREVIOUS_SYNC:
1492abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagBefore;
1493abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
1494abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_NEXT_SYNC:
1495abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagAfter;
1496abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
1497abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST_SYNC:
1498abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST:
1499abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagClosest;
1500abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
1501abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            default:
1502abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                CHECK(!"Should not be here.");
1503abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
1504abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
1505abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
150620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        uint32_t sampleIndex;
1507abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        status_t err = mSampleTable->findSampleAtTime(
150820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                seekTimeUs * mTimescale / 1000000,
1509abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                &sampleIndex, findFlags);
1510abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
1511abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
1512abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // We found the closest sample already, now we want the sync
1513abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // sample preceding it (or the sample itself of course), even
1514abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // if the subsequent sync sample is closer.
1515abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            findFlags = SampleTable::kFlagBefore;
1516abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
1517abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
1518abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleIndex;
1519abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (err == OK) {
1520abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            err = mSampleTable->findSyncSampleNear(
1521abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    sampleIndex, &syncSampleIndex, findFlags);
1522abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
152320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
152420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (err != OK) {
15255295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            if (err == ERROR_OUT_OF_RANGE) {
15265295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // An attempt to seek past the end of the stream would
15275295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // normally cause this ERROR_OUT_OF_RANGE error. Propagating
15285295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // this all the way to the MediaPlayer would cause abnormal
15295295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // termination. Legacy behaviour appears to be to behave as if
15305295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // we had seeked to the end of stream, ending normally.
15315295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                err = ERROR_END_OF_STREAM;
15325295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            }
153320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return err;
153420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
153520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1536abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t sampleTime;
1537abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
1538abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    sampleIndex, NULL, NULL, &sampleTime));
1539abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
1540abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
1541abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
1542abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
1543abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
1544abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#if 0
1545abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleTime;
1546abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
1547abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    syncSampleIndex, NULL, NULL, &syncSampleTime));
1548abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
1549abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        LOGI("seek to time %lld us => sample at time %lld us, "
1550abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             "sync sample at time %lld us",
1551abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             seekTimeUs,
1552abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             sampleTime * 1000000ll / mTimescale,
1553abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             syncSampleTime * 1000000ll / mTimescale);
1554abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#endif
1555abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
1556abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        mCurrentSampleIndex = syncSampleIndex;
155720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mBuffer != NULL) {
155820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
155920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
156020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
156120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
156220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // fall through
156320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
156420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15650024245e134467d120b40099da16c467dc365e76Andreas Huber    off_t offset;
15660024245e134467d120b40099da16c467dc365e76Andreas Huber    size_t size;
1567dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    uint32_t dts;
15688bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    bool isSyncSample;
1569dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool newBuffer = false;
1570dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (mBuffer == NULL) {
1571dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        newBuffer = true;
157220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1573c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        status_t err =
1574c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber            mSampleTable->getMetaDataForSample(
15758bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                    mCurrentSampleIndex, &offset, &size, &dts, &isSyncSample);
157620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1577dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
1578dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
1579dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
1580dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1581dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        err = mGroup->acquire_buffer(&mBuffer);
1582c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
1583dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
1584dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK_EQ(mBuffer, NULL);
1585dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
1586dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
15870024245e134467d120b40099da16c467dc365e76Andreas Huber    }
158820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1589dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (!mIsAVC || mWantsNALFragments) {
1590dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (newBuffer) {
1591dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ssize_t num_bytes_read =
159234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
1593dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1594dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            if (num_bytes_read < (ssize_t)size) {
1595dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer->release();
1596dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer = NULL;
1597dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1598dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                return ERROR_IO;
1599dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            }
1600dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
16017b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber            CHECK(mBuffer != NULL);
1602dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->set_range(0, size);
1603dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->meta_data()->clear();
160448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mBuffer->meta_data()->setInt64(
160548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                    kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
1606abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
1607abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            if (targetSampleTimeUs >= 0) {
1608abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                mBuffer->meta_data()->setInt64(
1609abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                        kKeyTargetTime, targetSampleTimeUs);
1610abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            }
1611abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
16128bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            if (isSyncSample) {
16138bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
16148bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            }
16158bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
1616dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ++mCurrentSampleIndex;
1617dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
1618dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1619dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (!mIsAVC) {
1620dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            *out = mBuffer;
1621dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
1622dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1623dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return OK;
1624dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
1625dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1626dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Each NAL unit is split up into its constituent fragments and
1627dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // each one of them returned in its own buffer.
1628dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
16296064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(mBuffer->range_length() >= mNALLengthSize);
1630dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1631dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        const uint8_t *src =
1632dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
1633dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
16346064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t nal_size = parseNALSize(src);
1635e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
1636e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            LOGE("incomplete NAL unit.");
1637e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
1638e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer->release();
1639e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer = NULL;
1640e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
1641e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            return ERROR_MALFORMED;
1642e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        }
1643dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1644dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        MediaBuffer *clone = mBuffer->clone();
16457b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(clone != NULL);
16466064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
1647dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
16487b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(mBuffer != NULL);
1649dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mBuffer->set_range(
16506064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_offset() + mNALLengthSize + nal_size,
16516064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_length() - mNALLengthSize - nal_size);
1652dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1653dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (mBuffer->range_length() == 0) {
1654dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->release();
1655dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
1656dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
1657dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1658dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        *out = clone;
1659dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1660dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        return OK;
1661dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    } else {
1662dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Whole NAL units are returned but each fragment is prefixed by
1663dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // the start code (0x00 00 00 01).
1664dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
166520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        ssize_t num_bytes_read =
166634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            mDataSource->readAt(offset, mSrcBuffer, size);
166720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
166820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (num_bytes_read < (ssize_t)size) {
166920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
167020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
167120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1672dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return ERROR_IO;
167320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
167420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1675dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        uint8_t *dstData = (uint8_t *)mBuffer->data();
1676dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        size_t srcOffset = 0;
1677dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        size_t dstOffset = 0;
16786064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
1679dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        while (srcOffset < size) {
16806064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            CHECK(srcOffset + mNALLengthSize <= size);
16816064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            size_t nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
16826064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            srcOffset += mNALLengthSize;
1683e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
1684e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            if (srcOffset + nalLength > size) {
1685e8a084958c27327b0aca749f69095605d2a21309Andreas Huber                mBuffer->release();
1686e8a084958c27327b0aca749f69095605d2a21309Andreas Huber                mBuffer = NULL;
1687e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
1688e8a084958c27327b0aca749f69095605d2a21309Andreas Huber                return ERROR_MALFORMED;
1689e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            }
1690dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1691dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            if (nalLength == 0) {
1692dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                continue;
1693dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            }
1694dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1695dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(dstOffset + 4 <= mBuffer->size());
1696dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1697dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            dstData[dstOffset++] = 0;
1698dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            dstData[dstOffset++] = 0;
1699dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            dstData[dstOffset++] = 0;
1700dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            dstData[dstOffset++] = 1;
1701dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
1702dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            srcOffset += nalLength;
1703dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            dstOffset += nalLength;
1704dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
17056064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK_EQ(srcOffset, size);
1706dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
17077b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(mBuffer != NULL);
1708dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mBuffer->set_range(0, dstOffset);
170920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->meta_data()->clear();
171048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        mBuffer->meta_data()->setInt64(
171148c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
1712abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
1713abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (targetSampleTimeUs >= 0) {
1714abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            mBuffer->meta_data()->setInt64(
1715abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    kKeyTargetTime, targetSampleTimeUs);
1716abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
1717abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
17188bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        if (isSyncSample) {
17198bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
17208bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        }
17218bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
172220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        ++mCurrentSampleIndex;
172320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
172420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        *out = mBuffer;
172520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
172620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
172720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
172820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
172920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
173020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17311b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool LegacySniffMPEG4(
1732693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
173320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[8];
173420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
173534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    ssize_t n = source->readAt(4, header, sizeof(header));
173620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (n < (ssize_t)sizeof(header)) {
173720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return false;
173820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
173920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
174020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
1741b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8)
1742b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8)
17430dba73763a04d39faf999dcc5ef12af3c99535a7Andreas Huber        || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
1744ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
1745983b449a27b5fa91eca82ede5204b4341899be62Andreas Huber        || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
174618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
17475a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        *confidence = 0.4;
174820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
174920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return true;
175020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
175120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
175220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return false;
175320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
175420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17551b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool isCompatibleBrand(uint32_t fourcc) {
17561b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    static const uint32_t kCompatibleBrands[] = {
17571b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', 'm'),
17581b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', '2'),
17591b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('a', 'v', 'c', '1'),
17601b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('3', 'g', 'p', '4'),
17611b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '1'),
17621b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '2'),
17631b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    };
17641b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
17651b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    for (size_t i = 0;
17661b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]);
17671b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         ++i) {
17681b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        if (kCompatibleBrands[i] == fourcc) {
17691b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            return true;
17701b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
17711b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
17721b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
17731b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
17741b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
17751b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
17761b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// Attempt to actually parse the 'ftyp' atom and determine if a suitable
17771b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// compatible brand is present.
17781b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool BetterSniffMPEG4(
17791b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
17801b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    uint8_t header[12];
17811b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    if (source->readAt(0, header, 12) != 12
17821b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            || memcmp("ftyp", &header[4], 4)) {
17831b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return false;
17841b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
17851b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
17861b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    size_t atomSize = U32_AT(&header[0]);
17871b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    if (atomSize < 16 || (atomSize % 4) != 0) {
17881b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return false;
17891b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
17901b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
17911b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    bool success = false;
17921b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    if (isCompatibleBrand(U32_AT(&header[8]))) {
17931b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        success = true;
17941b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    } else {
17951b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        size_t numCompatibleBrands = (atomSize - 16) / 4;
17961b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        for (size_t i = 0; i < numCompatibleBrands; ++i) {
17971b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            uint8_t tmp[4];
17981b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            if (source->readAt(16 + i * 4, tmp, 4) != 4) {
17991b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                return false;
18001b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
18011b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
18021b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            if (isCompatibleBrand(U32_AT(&tmp[0]))) {
18031b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                success = true;
18041b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                break;
18051b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
18061b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
18071b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
18081b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
18091b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    if (!success) {
18101b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return false;
18111b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
18121b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
18131b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
18145a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber    *confidence = 0.4f;
18151b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
18161b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return true;
18171b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
18181b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
18191b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberbool SniffMPEG4(
18205a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
18215a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        sp<AMessage> *) {
18221b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    if (BetterSniffMPEG4(source, mimeType, confidence)) {
18231b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
18241b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
18251b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
18261b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    if (LegacySniffMPEG4(source, mimeType, confidence)) {
18271b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        LOGW("Identified supported mpeg4 through LegacySniffMPEG4.");
18281b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
18291b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
18301b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
18311b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
18321b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
18331b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
183420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
183520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1836