MPEG4Extractor.cpp revision a65ccbff6e8eb301c0d325b2ec080aeda8df2024
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
50150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                if (mDataSource->flags() & DataSource::kWantsPrefetching) {
50250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    sp<MPEG4DataSource> cachedSource =
50350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                        new MPEG4DataSource(mDataSource);
50450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
50550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
50650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                        mDataSource = cachedSource;
50750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    }
50850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                }
5091edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber
5101edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber                mLastTrack->sampleTable = new SampleTable(mDataSource);
51150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            }
51250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
5136f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber            bool isTrack = false;
514bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (chunk_type == FOURCC('t', 'r', 'a', 'k')) {
5156f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                isTrack = true;
5166f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
517bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                Track *track = new Track;
518bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->next = NULL;
519bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                if (mLastTrack) {
520bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    mLastTrack->next = track;
521bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                } else {
522bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    mFirstTrack = track;
523bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                }
524bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                mLastTrack = track;
525bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
526bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->meta = new MetaData;
527bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->includes_expensive_metadata = false;
5286f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                track->skipTrack = false;
529bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->timescale = 0;
530bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->meta->setCString(kKeyMIMEType, "application/octet-stream");
531bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
532bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
53320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            off_t stop_offset = *offset + chunk_size;
53420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset;
53520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
53620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
53720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
53820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
53920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
54020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
54120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
542bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
543bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
544bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
545bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
5466f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber            if (isTrack) {
5476f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                if (mLastTrack->skipTrack) {
5486f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    Track *cur = mFirstTrack;
5496f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
5506f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    if (cur == mLastTrack) {
5516f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        delete cur;
5526f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        mFirstTrack = mLastTrack = NULL;
5536f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    } else {
5546f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        while (cur && cur->next != mLastTrack) {
5556f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                            cur = cur->next;
5566f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        }
5576f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        cur->next = NULL;
5586f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        delete mLastTrack;
5596f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        mLastTrack = cur;
5606f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    }
5616f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
5626f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    return OK;
5636f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                }
5646f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
565bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                status_t err = verifyTrack(mLastTrack);
566bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
567bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                if (err != OK) {
568bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    return err;
569bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                }
570bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
57120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mHaveMetadata = true;
57220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
57320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return UNKNOWN_ERROR;  // Return a dummy error.
57420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
57520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
57620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
57720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
57820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'k', 'h', 'd'):
57920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
580bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (chunk_data_size < 4) {
581bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
582bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
58320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
58420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t version;
58534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(data_offset, &version, 1) < 1) {
58620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
58720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
58820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
58920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint64_t ctime, mtime, duration;
59020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int32_t id;
59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t width, height;
59220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
59320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
59420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (chunk_data_size != 36 + 60) {
59520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_MALFORMED;
59620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
59720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
59820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                uint8_t buffer[36 + 60];
59934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
60020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
60120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
60220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
60320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
60420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                ctime = U64_AT(&buffer[4]);
60520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mtime = U64_AT(&buffer[12]);
60620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                id = U32_AT(&buffer[20]);
60720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = U64_AT(&buffer[28]);
60820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                width = U32_AT(&buffer[88]);
60920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                height = U32_AT(&buffer[92]);
61020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else if (version == 0) {
61120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (chunk_data_size != 24 + 60) {
61220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_MALFORMED;
61320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
61420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
61520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                uint8_t buffer[24 + 60];
61634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
61720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
61820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
61920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
62020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                ctime = U32_AT(&buffer[4]);
62120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mtime = U32_AT(&buffer[8]);
62220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                id = U32_AT(&buffer[12]);
62320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = U32_AT(&buffer[20]);
62420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                width = U32_AT(&buffer[76]);
62520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                height = U32_AT(&buffer[80]);
62620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
62720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
62820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
62920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
63020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
63120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'h', 'd'):
63320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
63420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
63520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
63620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
63720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t version;
63934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
64020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, &version, sizeof(version))
64120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(version)) {
64220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
64320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
64420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            off_t timescale_offset;
64620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
64820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 16;
64920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else if (version == 0) {
65020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 8;
65120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
65220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
65320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
65420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
65520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t timescale;
65634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
65720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        timescale_offset, &timescale, sizeof(timescale))
65820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(timescale)) {
65920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
66020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
66120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->timescale = ntohl(timescale);
66320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            int64_t duration;
66520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
66634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
66720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration, sizeof(duration))
66820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration)) {
66920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
67020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
67120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = ntoh64(duration);
67220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
67320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                int32_t duration32;
67434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
67520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration32, sizeof(duration32))
67620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration32)) {
67720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
67820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
67920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = ntohl(duration32);
68020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
68148c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mLastTrack->meta->setInt64(
68248c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                    kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
68320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
68420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
68520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
68620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
68720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
68820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'd'):
68920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
69020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 8) {
69120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
69220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
69320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
69420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8];
695bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (chunk_data_size < (off_t)sizeof(buffer)) {
696bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
697bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
698bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
69934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
70020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, 8) < 8) {
70120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
70220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
70320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
70420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
70520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
70620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
70720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
70820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
70920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t entry_count = U32_AT(&buffer[4]);
71020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
71120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (entry_count > 1) {
71220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // For now we only support a single type of media per track.
7136f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
7146f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                mLastTrack->skipTrack = true;
7156f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                *offset += chunk_size;
7166f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                break;
71720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
71820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
71920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            off_t stop_offset = *offset + chunk_size;
72020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + 8;
72120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            for (uint32_t i = 0; i < entry_count; ++i) {
72220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
72320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
72420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
72520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
72620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
727bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
728bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
729bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
730bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
73120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
73220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
73320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
73420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
73520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
736371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
73720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
73820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8 + 20];
73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
74020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic AudioSampleEntry size.
74120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
74320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
74434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
74520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
74620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
74720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
74820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
74920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
75020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t num_channels = U16_AT(&buffer[16]);
75120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
75281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint16_t sample_size = U16_AT(&buffer[18]);
75381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
75481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
75518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB,
75681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                            FourCC2MIME(chunk_type))) {
75781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                // AMR NB audio is always mono, 8kHz
75881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                num_channels = 1;
75981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                sample_rate = 8000;
76081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB,
76118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber                               FourCC2MIME(chunk_type))) {
76281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                // AMR WB audio is always mono, 16kHz
76320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                num_channels = 1;
76481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                sample_rate = 16000;
76520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
76781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber#if 0
76881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            printf("*** coding='%s' %d channels, size %d, rate %d\n",
76981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                   chunk, num_channels, sample_size, sample_rate);
77081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber#endif
77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
77320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
77420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            off_t stop_offset = *offset + chunk_size;
77720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
77820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
77920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
78020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
78120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
78220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
78320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
784bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
785bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
786bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
787bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
78820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
78920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
79020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
79120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
79220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
79320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
79420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
7957be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber            mHasVideo = true;
7967be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
79720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[78];
79820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
79920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic VideoSampleEntry size.
80020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
80120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
80220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
80334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
80420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
80520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
80620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
80720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
80820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
80920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t width = U16_AT(&buffer[6 + 18]);
81020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t height = U16_AT(&buffer[6 + 20]);
81120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
812134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            // printf("*** coding='%s' width=%d height=%d\n",
813134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            //        chunk, width, height);
81420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
81520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
81620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyWidth, width);
81720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyHeight, height);
81820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
81920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            off_t stop_offset = *offset + chunk_size;
82020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
82120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
82220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
82320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
82420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
82520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
82620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
827bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
828bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
829bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
830bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
83120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
83220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
83320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
83420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'c', 'o'):
83520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('c', 'o', '6', '4'):
83620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
83720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
83820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setChunkOffsetParams(
83920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
84020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
84120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
84220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
84320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
84420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
84520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
84620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
84720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
84820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
84920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'c'):
85020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
85120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
85220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleToChunkParams(
85320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
85420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
85520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
85620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
85720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
85820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
85920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
86020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
86120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
86220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
86320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'z'):
86420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'z', '2'):
86520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
86620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
86720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleSizeParams(
86820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
86920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
87020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
87120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
87220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
87320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
874738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            size_t max_size;
875738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            CHECK_EQ(mLastTrack->sampleTable->getMaxSampleSize(&max_size), OK);
876738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber
877738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            // Assume that a given buffer only contains at most 10 fragments,
878738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            // each fragment originally prefixed with a 2 byte length will
879738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
880738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            // and thus will grow by 2 bytes per fragment.
881738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
882738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber
88320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
88420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
88520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
88620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
88720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 't', 's'):
88820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
88920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
89020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setTimeToSampleParams(
89120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
89220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
89320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
89420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
89520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
89620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
89720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
89820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
89920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
90020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
90120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 's'):
90220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
90320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
90420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSyncSampleParams(
90520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
90620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
90720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
90820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
90920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
91020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
91120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
91220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
91320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
91420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
91520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('e', 's', 'd', 's'):
91620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
91720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
91820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
91920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
92020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
92120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[256];
92220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size > (off_t)sizeof(buffer)) {
92320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
92420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
92520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
92634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
92720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
92820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
92920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
93020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
93120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
93220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
93320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
93420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
93520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
93620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
93720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
93820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
939ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            if (mPath.size() >= 2
940ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
941ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // Information from the ESDS must be relied on for proper
942ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // setup of sample rate and channel count for MPEG4 Audio.
943ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // The generic header appears to only contain generic
944ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // information...
945ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
946ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio(
947ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                        &buffer[4], chunk_data_size - 4);
948ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
949ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                if (err != OK) {
950ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    return err;
951ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                }
952ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            }
953ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
95420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
95520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
95620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
95720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
95820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', 'C'):
95920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
96020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            char buffer[256];
96120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size > (off_t)sizeof(buffer)) {
96220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
96320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
96420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
96534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
96620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
96720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
96820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
96920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
97020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
97120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    kKeyAVCC, kTypeAVCC, buffer, chunk_data_size);
97220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
97320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
97420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
97520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
97620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
97772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'e', 't', 'a'):
97872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
97972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            uint8_t buffer[4];
980bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (chunk_data_size < (off_t)sizeof(buffer)) {
981bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
982bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
983bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
98472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
98572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, buffer, 4) < 4) {
98672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
98772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
98872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
98972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (U32_AT(buffer) != 0) {
99072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                // Should be version 0, flags 0.
991ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
992ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // If it's not, let's assume this is one of those
993ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // apparently malformed chunks that don't have flags
994ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // and completely different semantics than what's
995ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // in the MPEG4 specs and skip it.
996ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                *offset += chunk_size;
997ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                return OK;
99872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
99972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
100072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            off_t stop_offset = *offset + chunk_size;
100172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset = data_offset + sizeof(buffer);
100272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            while (*offset < stop_offset) {
100372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                status_t err = parseChunk(offset, depth + 1);
100472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
100572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
100672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
100772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
1008bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1009bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1010bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1011bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
101272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
101372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
101472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
101572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('d', 'a', 't', 'a'):
101672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
101772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mPath.size() == 6 && underMetaDataPath(mPath)) {
101872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                status_t err = parseMetaData(data_offset, chunk_data_size);
101972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
102072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
102172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
102272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
102372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
102472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
102572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset += chunk_size;
102672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
102772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
102872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
102972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'v', 'h', 'd'):
103072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
103172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (chunk_data_size < 12) {
103272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_MALFORMED;
103372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
103472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
103572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            uint8_t header[12];
103672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
103772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, header, sizeof(header))
103872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    < (ssize_t)sizeof(header)) {
103972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
104072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
104172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
104272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            int64_t creationTime;
104372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (header[0] == 1) {
104472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U64_AT(&header[4]);
1045bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (header[0] != 0) {
1046bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
104772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            } else {
104872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U32_AT(&header[4]);
104972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
105072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
105172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            String8 s;
105272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            convertTimeToDate(creationTime, &s);
105372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
105472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(kKeyDate, s.string());
105572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
105672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset += chunk_size;
105772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
105872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
105972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
106020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
106120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
106220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
106320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
106420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
106520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
106620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
106720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
106820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
106920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
107072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatus_t MPEG4Extractor::parseMetaData(off_t offset, size_t size) {
107172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (size < 4) {
107272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_MALFORMED;
107372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
107472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
107572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint8_t *buffer = new uint8_t[size + 1];
107672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (mDataSource->readAt(
107772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                offset, buffer, size) != (ssize_t)size) {
107872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        delete[] buffer;
107972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        buffer = NULL;
108072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
108172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_IO;
108272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
108372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
108472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t flags = U32_AT(buffer);
108572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
108672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t metadataKey = 0;
108772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    switch (mPath[4]) {
108872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'a', 'l', 'b'):
108972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
109072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbum;
109172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
109272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
109372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'A', 'R', 'T'):
109472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
109572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyArtist;
109672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
109772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
109866ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        case FOURCC('a', 'A', 'R', 'T'):
109966ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        {
110066ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            metadataKey = kKeyAlbumArtist;
110166ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            break;
110266ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        }
110372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'd', 'a', 'y'):
110472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
110572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyYear;
110672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
110772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
110872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'n', 'a', 'm'):
110972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
111072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyTitle;
111172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
111272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
111372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'w', 'r', 't'):
111472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
111572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyWriter;
111672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
111772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
111872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('c', 'o', 'v', 'r'):
111972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
112072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbumArt;
112172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
112272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
112372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('g', 'n', 'r', 'e'):
112472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
112572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyGenre;
112672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
112772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
112826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC(0xa9, 'g', 'e', 'n'):
112926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
113026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            metadataKey = kKeyGenre;
113126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
113226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
113372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('t', 'r', 'k', 'n'):
113472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
113572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (size == 16 && flags == 0) {
113672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char tmp[16];
113772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                sprintf(tmp, "%d/%d",
113872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        (int)buffer[size - 5], (int)buffer[size - 3]);
113972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
114072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
114172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
114272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
114372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
114426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC('d', 'i', 's', 'k'):
114526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
114626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            if (size == 14 && flags == 0) {
114726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                char tmp[16];
114826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                sprintf(tmp, "%d/%d",
114926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                        (int)buffer[size - 3], (int)buffer[size - 1]);
115026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
115126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(kKeyDiscNumber, tmp);
115226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            }
115326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
115426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
115526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
115672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        default:
115772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
115872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
115972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
116072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (size >= 8 && metadataKey) {
116172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        if (metadataKey == kKeyAlbumArt) {
116272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setData(
116372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    kKeyAlbumArt, MetaData::TYPE_NONE,
116472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    buffer + 8, size - 8);
116572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else if (metadataKey == kKeyGenre) {
116672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (flags == 0) {
116726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // uint8_t genre code, iTunes genre codes are
116826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // the standard id3 codes, except they start
116926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // at 1 instead of 0 (e.g. Pop is 14, not 13)
117026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // We use standard id3 numbering, so subtract 1.
117126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                int genrecode = (int)buffer[size - 1];
117226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                genrecode--;
117326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                if (genrecode < 0) {
117426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                    genrecode = 255; // reserved for 'unknown genre'
117526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                }
117672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char genre[10];
117726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                sprintf(genre, "%d", genrecode);
117872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
117972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(metadataKey, genre);
118026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            } else if (flags == 1) {
118126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // custom genre string
118226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                buffer[size] = '\0';
118326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
118426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(
118526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                        metadataKey, (const char *)buffer + 8);
118672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
118772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else {
118872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            buffer[size] = '\0';
118972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
119072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(
119172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    metadataKey, (const char *)buffer + 8);
119272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
119372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
119472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
119572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    delete[] buffer;
119672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    buffer = NULL;
119772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
119872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return OK;
119972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
120072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1201693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
120220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
120320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
1204693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return NULL;
120520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
120620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
120720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
120820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
120920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
1210693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber            return NULL;
121120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
121220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
121320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
121420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
121520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
121620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1217371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
1218371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
1219371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
1220371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
1221693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    return new MPEG4Source(
122248c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            track->meta, mDataSource, track->timescale, track->sampleTable);
122320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
122420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1225bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber// static
1226bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) {
1227bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const char *mime;
1228bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    CHECK(track->meta->findCString(kKeyMIMEType, &mime));
1229bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1230bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    uint32_t type;
1231bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const void *data;
1232bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    size_t size;
1233bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
1234bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyAVCC, &type, &data, &size)
1235bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeAVCC) {
1236bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
1237bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
1238bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
1239bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
1240bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyESDS, &type, &data, &size)
1241bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeESDS) {
1242bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
1243bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
1244bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    }
1245bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1246bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    return OK;
1247bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber}
1248bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1249ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
1250ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        const void *esds_data, size_t esds_size) {
1251ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    ESDS esds(esds_data, esds_size);
125281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
125381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    uint8_t objectTypeIndication;
125481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
125581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return ERROR_MALFORMED;
125681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
125781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
125881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (objectTypeIndication == 0xe1) {
125981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        // This isn't MPEG4 audio at all, it's QCELP 14k...
126081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
126181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return OK;
126281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
126381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
1264ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    const uint8_t *csd;
1265ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    size_t csd_size;
1266ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (esds.getCodecSpecificInfo(
1267ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                (const void **)&csd, &csd_size) != OK) {
1268ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
1269ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
1270ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1271ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#if 0
1272ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    printf("ESD of size %d\n", csd_size);
1273ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    hexdump(csd, csd_size);
1274ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#endif
1275ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1276a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    if (csd_size == 0) {
1277a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // There's no further information, i.e. no codec specific data
1278a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // Let's assume that the information provided in the mpeg4 headers
1279a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // is accurate and hope for the best.
1280a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
1281a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        return OK;
1282a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    }
1283a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
1284ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (csd_size < 2) {
1285ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
1286ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
1287ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1288ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    uint32_t objectType = csd[0] >> 3;
1289ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1290ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (objectType == 31) {
1291ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_UNSUPPORTED;
1292ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
1293ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1294ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    uint32_t freqIndex = (csd[0] & 7) << 1 | (csd[1] >> 7);
1295ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t sampleRate = 0;
1296ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t numChannels = 0;
1297ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (freqIndex == 15) {
1298ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        if (csd_size < 5) {
1299ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            return ERROR_MALFORMED;
1300ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
1301ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1302ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        sampleRate = (csd[1] & 0x7f) << 17
1303ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                        | csd[2] << 9
1304ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                        | csd[3] << 1
1305ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                        | (csd[4] >> 7);
1306ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1307ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        numChannels = (csd[4] >> 3) & 15;
1308ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    } else {
13093c3ddfa39635a2d39f4ee7c966fb9403fe1ec9d8Andreas Huber        static uint32_t kSamplingRate[] = {
13103c3ddfa39635a2d39f4ee7c966fb9403fe1ec9d8Andreas Huber            96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
13113c3ddfa39635a2d39f4ee7c966fb9403fe1ec9d8Andreas Huber            16000, 12000, 11025, 8000, 7350
13123c3ddfa39635a2d39f4ee7c966fb9403fe1ec9d8Andreas Huber        };
1313ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1314ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        if (freqIndex == 13 || freqIndex == 14) {
1315ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            return ERROR_MALFORMED;
1316ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
1317ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1318ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        sampleRate = kSamplingRate[freqIndex];
1319ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        numChannels = (csd[1] >> 3) & 15;
1320ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
1321ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1322ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (numChannels == 0) {
1323ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_UNSUPPORTED;
1324ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
1325ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1326ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevSampleRate;
1327ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
1328ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1329ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevSampleRate != sampleRate) {
1330ec9dd59902c8beea4ba6a842f3a843d46150d949Andreas Huber        LOGV("mpeg4 audio sample rate different from previous setting. "
1331ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevSampleRate, sampleRate);
1332ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
1333ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1334ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
1335ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1336ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevChannelCount;
1337ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
1338ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1339ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevChannelCount != numChannels) {
1340ec9dd59902c8beea4ba6a842f3a843d46150d949Andreas Huber        LOGV("mpeg4 audio channel count different from previous setting. "
1341ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevChannelCount, numChannels);
1342ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
1343ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1344ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
1345ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1346ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    return OK;
1347ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber}
1348ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
134920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
135020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
135120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::MPEG4Source(
135220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        const sp<MetaData> &format,
1353693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &dataSource,
135448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        int32_t timeScale,
1355693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<SampleTable> &sampleTable)
135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mFormat(format),
135720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDataSource(dataSource),
135848c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber      mTimescale(timeScale),
135920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSampleTable(sampleTable),
136020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCurrentSampleIndex(0),
136120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mIsAVC(false),
13626064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber      mNALLengthSize(0),
136320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mStarted(false),
136420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mGroup(NULL),
136520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mBuffer(NULL),
1366dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber      mWantsNALFragments(false),
13670024245e134467d120b40099da16c467dc365e76Andreas Huber      mSrcBuffer(NULL) {
136820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
136920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mFormat->findCString(kKeyMIMEType, &mime);
1370dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(success);
137120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
137218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber    mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
13736064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
13746064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    if (mIsAVC) {
13756064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        uint32_t type;
13766064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const void *data;
13776064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t size;
13786064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(format->findData(kKeyAVCC, &type, &data, &size));
13796064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
13806064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const uint8_t *ptr = (const uint8_t *)data;
13816064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
13826064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(size >= 7);
13836064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK_EQ(ptr[0], 1);  // configurationVersion == 1
13846064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
13856064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        // The number of bytes used to encode the length of a NAL unit.
13866064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        mNALLengthSize = 1 + (ptr[4] & 3);
13876064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
138820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
138920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
139020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::~MPEG4Source() {
139120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mStarted) {
139220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        stop();
139320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
139420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
139520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
139620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::start(MetaData *params) {
13977b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
13987b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
1399dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(!mStarted);
140020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
140120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t val;
1402dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (params && params->findInt32(kKeyWantsNALFragments, &val)
140320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        && val != 0) {
1404dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = true;
140520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    } else {
1406dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = false;
140720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
140820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
140920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = new MediaBufferGroup;
141020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1411738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    int32_t max_size;
1412738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
141320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1414738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    mGroup->add_buffer(new MediaBuffer(max_size));
14150024245e134467d120b40099da16c467dc365e76Andreas Huber
14160024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = new uint8_t[max_size];
141720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
141820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = true;
141920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
142020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
142120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
142220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
142320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::stop() {
14247b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
14257b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
1426dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
142720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
142820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mBuffer != NULL) {
142920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->release();
143020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
143120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
143220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14330024245e134467d120b40099da16c467dc365e76Andreas Huber    delete[] mSrcBuffer;
14340024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = NULL;
14350024245e134467d120b40099da16c467dc365e76Andreas Huber
143620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    delete mGroup;
143720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = NULL;
143820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
143920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = false;
144020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mCurrentSampleIndex = 0;
144120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
144220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
144320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
144420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
144520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> MPEG4Source::getFormat() {
14467b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
14477b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
144820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return mFormat;
144920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
145020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14516064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const {
14526064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    switch (mNALLengthSize) {
14536064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 1:
14546064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return *data;
14556064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 2:
14566064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U16_AT(data);
14576064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 3:
14586064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return ((size_t)data[0] << 16) | U16_AT(&data[1]);
14596064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 4:
14606064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U32_AT(data);
14616064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
14626064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
14636064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // This cannot happen, mNALLengthSize springs to life by adding 1 to
14646064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // a 2-bit integer.
14656064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    CHECK(!"Should not be here.");
14666064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
14676064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    return 0;
14686064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber}
14696064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
147020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::read(
147120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
14727b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
14737b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
1474dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
147520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
147620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *out = NULL;
147720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1478abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    int64_t targetSampleTimeUs = -1;
1479abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
148020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t seekTimeUs;
1481abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
1482abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
1483abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t findFlags = 0;
1484abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        switch (mode) {
1485abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_PREVIOUS_SYNC:
1486abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagBefore;
1487abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
1488abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_NEXT_SYNC:
1489abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagAfter;
1490abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
1491abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST_SYNC:
1492abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST:
1493abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagClosest;
1494abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
1495abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            default:
1496abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                CHECK(!"Should not be here.");
1497abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
1498abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
1499abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
150020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        uint32_t sampleIndex;
1501abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        status_t err = mSampleTable->findSampleAtTime(
150220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                seekTimeUs * mTimescale / 1000000,
1503abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                &sampleIndex, findFlags);
1504abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
1505abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
1506abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // We found the closest sample already, now we want the sync
1507abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // sample preceding it (or the sample itself of course), even
1508abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // if the subsequent sync sample is closer.
1509abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            findFlags = SampleTable::kFlagBefore;
1510abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
1511abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
1512abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleIndex;
1513abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (err == OK) {
1514abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            err = mSampleTable->findSyncSampleNear(
1515abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    sampleIndex, &syncSampleIndex, findFlags);
1516abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
151720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
151820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (err != OK) {
15195295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            if (err == ERROR_OUT_OF_RANGE) {
15205295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // An attempt to seek past the end of the stream would
15215295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // normally cause this ERROR_OUT_OF_RANGE error. Propagating
15225295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // this all the way to the MediaPlayer would cause abnormal
15235295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // termination. Legacy behaviour appears to be to behave as if
15245295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // we had seeked to the end of stream, ending normally.
15255295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                err = ERROR_END_OF_STREAM;
15265295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            }
152720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return err;
152820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
152920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1530abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t sampleTime;
1531abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
1532abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    sampleIndex, NULL, NULL, &sampleTime));
1533abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
1534abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
1535abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
1536abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
1537abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
1538abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#if 0
1539abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleTime;
1540abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
1541abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    syncSampleIndex, NULL, NULL, &syncSampleTime));
1542abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
1543abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        LOGI("seek to time %lld us => sample at time %lld us, "
1544abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             "sync sample at time %lld us",
1545abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             seekTimeUs,
1546abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             sampleTime * 1000000ll / mTimescale,
1547abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             syncSampleTime * 1000000ll / mTimescale);
1548abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#endif
1549abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
1550abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        mCurrentSampleIndex = syncSampleIndex;
155120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mBuffer != NULL) {
155220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
155320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
155420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
155520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
155620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // fall through
155720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
155820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15590024245e134467d120b40099da16c467dc365e76Andreas Huber    off_t offset;
15600024245e134467d120b40099da16c467dc365e76Andreas Huber    size_t size;
1561dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    uint32_t dts;
15628bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    bool isSyncSample;
1563dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool newBuffer = false;
1564dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (mBuffer == NULL) {
1565dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        newBuffer = true;
156620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1567c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        status_t err =
1568c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber            mSampleTable->getMetaDataForSample(
15698bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                    mCurrentSampleIndex, &offset, &size, &dts, &isSyncSample);
157020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1571dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
1572dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
1573dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
1574dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1575dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        err = mGroup->acquire_buffer(&mBuffer);
1576c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
1577dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
1578dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK_EQ(mBuffer, NULL);
1579dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
1580dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
15810024245e134467d120b40099da16c467dc365e76Andreas Huber    }
158220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1583dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (!mIsAVC || mWantsNALFragments) {
1584dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (newBuffer) {
1585dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ssize_t num_bytes_read =
158634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
1587dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1588dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            if (num_bytes_read < (ssize_t)size) {
1589dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer->release();
1590dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer = NULL;
1591dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1592dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                return ERROR_IO;
1593dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            }
1594dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
15957b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber            CHECK(mBuffer != NULL);
1596dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->set_range(0, size);
1597dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->meta_data()->clear();
159848c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mBuffer->meta_data()->setInt64(
159948c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                    kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
1600abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
1601abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            if (targetSampleTimeUs >= 0) {
1602abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                mBuffer->meta_data()->setInt64(
1603abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                        kKeyTargetTime, targetSampleTimeUs);
1604abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            }
1605abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
16068bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            if (isSyncSample) {
16078bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
16088bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            }
16098bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
1610dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ++mCurrentSampleIndex;
1611dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
1612dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1613dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (!mIsAVC) {
1614dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            *out = mBuffer;
1615dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
1616dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1617dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return OK;
1618dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
1619dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1620dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Each NAL unit is split up into its constituent fragments and
1621dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // each one of them returned in its own buffer.
1622dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
16236064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(mBuffer->range_length() >= mNALLengthSize);
1624dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1625dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        const uint8_t *src =
1626dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
1627dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
16286064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t nal_size = parseNALSize(src);
1629e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
1630e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            LOGE("incomplete NAL unit.");
1631e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
1632e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer->release();
1633e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer = NULL;
1634e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
1635e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            return ERROR_MALFORMED;
1636e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        }
1637dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1638dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        MediaBuffer *clone = mBuffer->clone();
16397b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(clone != NULL);
16406064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
1641dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
16427b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(mBuffer != NULL);
1643dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mBuffer->set_range(
16446064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_offset() + mNALLengthSize + nal_size,
16456064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_length() - mNALLengthSize - nal_size);
1646dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1647dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (mBuffer->range_length() == 0) {
1648dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->release();
1649dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
1650dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
1651dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1652dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        *out = clone;
1653dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1654dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        return OK;
1655dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    } else {
1656dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Whole NAL units are returned but each fragment is prefixed by
1657dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // the start code (0x00 00 00 01).
1658dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
165920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        ssize_t num_bytes_read =
166034769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            mDataSource->readAt(offset, mSrcBuffer, size);
166120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
166220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (num_bytes_read < (ssize_t)size) {
166320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
166420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
166520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1666dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return ERROR_IO;
166720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
166820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1669dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        uint8_t *dstData = (uint8_t *)mBuffer->data();
1670dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        size_t srcOffset = 0;
1671dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        size_t dstOffset = 0;
16726064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
1673dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        while (srcOffset < size) {
16746064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            CHECK(srcOffset + mNALLengthSize <= size);
16756064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            size_t nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
16766064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            srcOffset += mNALLengthSize;
1677e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
1678e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            if (srcOffset + nalLength > size) {
1679e8a084958c27327b0aca749f69095605d2a21309Andreas Huber                mBuffer->release();
1680e8a084958c27327b0aca749f69095605d2a21309Andreas Huber                mBuffer = NULL;
1681e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
1682e8a084958c27327b0aca749f69095605d2a21309Andreas Huber                return ERROR_MALFORMED;
1683e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            }
1684dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1685dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            if (nalLength == 0) {
1686dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                continue;
1687dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            }
1688dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1689dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(dstOffset + 4 <= mBuffer->size());
1690dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
1691dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            dstData[dstOffset++] = 0;
1692dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            dstData[dstOffset++] = 0;
1693dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            dstData[dstOffset++] = 0;
1694dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            dstData[dstOffset++] = 1;
1695dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
1696dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            srcOffset += nalLength;
1697dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            dstOffset += nalLength;
1698dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
16996064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK_EQ(srcOffset, size);
1700dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
17017b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(mBuffer != NULL);
1702dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mBuffer->set_range(0, dstOffset);
170320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->meta_data()->clear();
170448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        mBuffer->meta_data()->setInt64(
170548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
1706abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
1707abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (targetSampleTimeUs >= 0) {
1708abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            mBuffer->meta_data()->setInt64(
1709abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    kKeyTargetTime, targetSampleTimeUs);
1710abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
1711abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
17128bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        if (isSyncSample) {
17138bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
17148bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        }
17158bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
171620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        ++mCurrentSampleIndex;
171720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
171820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        *out = mBuffer;
171920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
172020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
172120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
172220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
172320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
172420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17251b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool LegacySniffMPEG4(
1726693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
172720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[8];
172820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
172934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    ssize_t n = source->readAt(4, header, sizeof(header));
173020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (n < (ssize_t)sizeof(header)) {
173120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return false;
173220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
173320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
173420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
1735b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8)
1736b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8)
17370dba73763a04d39faf999dcc5ef12af3c99535a7Andreas Huber        || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
1738ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
1739983b449a27b5fa91eca82ede5204b4341899be62Andreas Huber        || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
174018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
174120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        *confidence = 0.1;
174220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
174320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return true;
174420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
174520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
174620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return false;
174720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
174820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17491b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool isCompatibleBrand(uint32_t fourcc) {
17501b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    static const uint32_t kCompatibleBrands[] = {
17511b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', 'm'),
17521b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', '2'),
17531b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('a', 'v', 'c', '1'),
17541b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('3', 'g', 'p', '4'),
17551b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '1'),
17561b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '2'),
17571b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    };
17581b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
17591b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    for (size_t i = 0;
17601b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]);
17611b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         ++i) {
17621b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        if (kCompatibleBrands[i] == fourcc) {
17631b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            return true;
17641b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
17651b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
17661b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
17671b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
17681b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
17691b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
17701b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// Attempt to actually parse the 'ftyp' atom and determine if a suitable
17711b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// compatible brand is present.
17721b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool BetterSniffMPEG4(
17731b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
17741b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    uint8_t header[12];
17751b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    if (source->readAt(0, header, 12) != 12
17761b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            || memcmp("ftyp", &header[4], 4)) {
17771b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return false;
17781b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
17791b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
17801b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    size_t atomSize = U32_AT(&header[0]);
17811b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    if (atomSize < 16 || (atomSize % 4) != 0) {
17821b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return false;
17831b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
17841b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
17851b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    bool success = false;
17861b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    if (isCompatibleBrand(U32_AT(&header[8]))) {
17871b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        success = true;
17881b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    } else {
17891b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        size_t numCompatibleBrands = (atomSize - 16) / 4;
17901b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        for (size_t i = 0; i < numCompatibleBrands; ++i) {
17911b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            uint8_t tmp[4];
17921b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            if (source->readAt(16 + i * 4, tmp, 4) != 4) {
17931b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                return false;
17941b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
17951b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
17961b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            if (isCompatibleBrand(U32_AT(&tmp[0]))) {
17971b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                success = true;
17981b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                break;
17991b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
18001b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
18011b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
18021b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
18031b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    if (!success) {
18041b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return false;
18051b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
18061b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
18071b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
18081b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    *confidence = 0.3f;
18091b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
18101b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return true;
18111b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
18121b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
18131b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberbool SniffMPEG4(
18141b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
18151b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    if (BetterSniffMPEG4(source, mimeType, confidence)) {
18161b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
18171b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
18181b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
18191b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    if (LegacySniffMPEG4(source, mimeType, confidence)) {
18201b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        LOGW("Identified supported mpeg4 through LegacySniffMPEG4.");
18211b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
18221b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
18231b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
18241b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
18251b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
18261b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
182720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
182820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1829