MPEG4Extractor.cpp revision f810a8298aea13fa177060cdc10c8297eac69c49
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
1756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen//#define LOG_NDEBUG 0
1820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#define LOG_TAG "MPEG4Extractor"
1920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/Log.h>
2020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2166326a5ee0869f1ee4d136a477e6effba428b3cbAndreas Huber#include "include/MPEG4Extractor.h"
2289e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber#include "include/SampleTable.h"
237a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang#include "include/ESDS.h"
2489e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber
2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <ctype.h>
2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <stdint.h>
2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <stdlib.h>
2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <string.h>
2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke#include <media/stagefright/foundation/ABitReader.h>
31d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson#include <media/stagefright/foundation/ABuffer.h>
32ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#include <media/stagefright/foundation/ADebug.h>
33a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber#include <media/stagefright/foundation/AMessage.h>
3467a30ebfe785f7cd5ecfb0d2fb487e54536a3d48Lajos Molnar#include <media/stagefright/foundation/AUtils.h>
3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
3620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBufferGroup.h>
3718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/String8.h>
4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Source : public MediaSource {
4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
4620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Caller retains ownership of both "dataSource" and "sampleTable".
47693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    MPEG4Source(const sp<MetaData> &format,
48693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber                const sp<DataSource> &dataSource,
4948c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                int32_t timeScale,
5005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                const sp<SampleTable> &sampleTable,
5105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                Vector<SidxEntry> &sidx,
5205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                off64_t firstMoofOffset);
5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t start(MetaData *params = NULL);
5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t stop();
5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual sp<MetaData> getFormat();
5820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL);
6005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    virtual status_t fragmentedRead(MediaBuffer **buffer, const ReadOptions *options = NULL);
6120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
62693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huberprotected:
63693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    virtual ~MPEG4Source();
64693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber
6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
667b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex mLock;
677b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mFormat;
69693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<DataSource> mDataSource;
7020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t mTimescale;
71693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<SampleTable> mSampleTable;
7220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t mCurrentSampleIndex;
7305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t mCurrentFragmentIndex;
7405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Vector<SidxEntry> &mSegments;
7505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mFirstMoofOffset;
7605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mCurrentMoofOffset;
7705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mNextMoofOffset;
7805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t mCurrentTime;
7905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int32_t mLastParsedTrackId;
8005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int32_t mTrackId;
8120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
82ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int32_t mCryptoMode;    // passed in from extractor
83ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int32_t mDefaultIVSize; // passed in from extractor
84ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t mCryptoKey[16]; // passed in from extractor
85ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentAuxInfoType;
86ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentAuxInfoTypeParameter;
8748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    int32_t mCurrentDefaultSampleInfoSize;
88ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoCount;
89ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoAllocSize;
90ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t* mCurrentSampleInfoSizes;
91ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoOffsetCount;
92ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoOffsetsAllocSize;
93ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint64_t* mCurrentSampleInfoOffsets;
94ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
9520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mIsAVC;
966064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    size_t mNALLengthSize;
976064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
9820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mStarted;
9920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBufferGroup *mGroup;
10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *mBuffer;
10320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
104dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool mWantsNALFragments;
10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1060024245e134467d120b40099da16c467dc365e76Andreas Huber    uint8_t *mSrcBuffer;
1070024245e134467d120b40099da16c467dc365e76Andreas Huber
1086064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    size_t parseNALSize(const uint8_t *data) const;
10905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseChunk(off64_t *offset);
11005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseTrackFragmentHeader(off64_t offset, off64_t size);
11105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseTrackFragmentRun(off64_t offset, off64_t size);
112ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    status_t parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size);
113ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    status_t parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size);
11405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
11505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    struct TrackFragmentHeaderInfo {
11605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        enum Flags {
11705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kBaseDataOffsetPresent         = 0x01,
11805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kSampleDescriptionIndexPresent = 0x02,
11905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleDurationPresent  = 0x08,
12005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleSizePresent      = 0x10,
12105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleFlagsPresent     = 0x20,
12205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDurationIsEmpty               = 0x10000,
12305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        };
12405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
12505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mTrackID;
12605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mFlags;
12705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint64_t mBaseDataOffset;
12805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mSampleDescriptionIndex;
12905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleDuration;
13005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleSize;
13105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleFlags;
13205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
13305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint64_t mDataOffset;
13405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
13505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    TrackFragmentHeaderInfo mTrackFragmentHeaderInfo;
13605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
13705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    struct Sample {
13805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t offset;
13905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size_t size;
14005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t duration;
141ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        uint8_t iv[16];
142ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Vector<size_t> clearsizes;
143ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Vector<size_t> encryptedsizes;
14405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
14505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Vector<Sample> mCurrentSamples;
1466064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
14720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source(const MPEG4Source &);
14820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source &operator=(const MPEG4Source &);
14920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
15020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This custom data source wraps an existing one and satisfies requests
15250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// falling entirely within a cached range from the cache while forwarding
15350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// all remaining requests to the wrapped datasource.
15450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This is used to cache the full sampletable metadata for a single track,
15550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// possibly wrapping multiple times to cover all tracks, i.e.
15650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// Each MPEG4DataSource caches the sampletable metadata for a single track.
15750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
15850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstruct MPEG4DataSource : public DataSource {
15950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource(const sp<DataSource> &source);
16050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
16150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual status_t initCheck() const;
162c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
163c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    virtual status_t getSize(off64_t *size);
16450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual uint32_t flags();
16550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
166c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    status_t setCachedRange(off64_t offset, size_t size);
16750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
16850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprotected:
16950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual ~MPEG4DataSource();
17050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprivate:
17250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex mLock;
17350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    sp<DataSource> mSource;
175c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t mCachedOffset;
17650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    size_t mCachedSize;
17750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    uint8_t *mCache;
17850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    void clearCache();
18050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource(const MPEG4DataSource &);
18250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource &operator=(const MPEG4DataSource &);
18350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber};
18450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source)
18650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    : mSource(source),
18750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCachedOffset(0),
18850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCachedSize(0),
18950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCache(NULL) {
19050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
19150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::~MPEG4DataSource() {
19350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    clearCache();
19450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
19550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Hubervoid MPEG4DataSource::clearCache() {
19750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (mCache) {
19850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        free(mCache);
19950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        mCache = NULL;
20050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
20150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
20250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedOffset = 0;
20350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedSize = 0;
20450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
20550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
20650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstatus_t MPEG4DataSource::initCheck() const {
20750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->initCheck();
20850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
20950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
210c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongssize_t MPEG4DataSource::readAt(off64_t offset, void *data, size_t size) {
21150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex::Autolock autoLock(mLock);
21250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
21367a30ebfe785f7cd5ecfb0d2fb487e54536a3d48Lajos Molnar    if (isInRange(mCachedOffset, mCachedSize, offset, size)) {
21450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        memcpy(data, &mCache[offset - mCachedOffset], size);
21550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return size;
21650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
21750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
21850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->readAt(offset, data, size);
21950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
22050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
221c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4DataSource::getSize(off64_t *size) {
22250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->getSize(size);
22350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
22450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
22550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberuint32_t MPEG4DataSource::flags() {
22650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->flags();
22750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
22850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
229c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4DataSource::setCachedRange(off64_t offset, size_t size) {
23050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex::Autolock autoLock(mLock);
23150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
23250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    clearCache();
23350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
23450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCache = (uint8_t *)malloc(size);
23550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
23650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (mCache == NULL) {
23750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return -ENOMEM;
23850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
23950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
24050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedOffset = offset;
24150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedSize = size;
24250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
24350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    ssize_t err = mSource->readAt(mCachedOffset, mCache, mCachedSize);
24450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
24550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (err < (ssize_t)size) {
24650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        clearCache();
24750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
24850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return ERROR_IO;
24950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
25050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
25150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return OK;
25250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
25350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
25450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber////////////////////////////////////////////////////////////////////////////////
25550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
25620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatic void hexdump(const void *_data, size_t size) {
25720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const uint8_t *data = (const uint8_t *)_data;
25820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t offset = 0;
25920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (offset < size) {
26020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf("0x%04x  ", offset);
26120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        size_t n = size - offset;
26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (n > 16) {
26420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            n = 16;
26520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
26620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < 16; ++i) {
26820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (i == 8) {
26920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(" ");
27020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
27120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (offset + i < size) {
27320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%02x ", data[offset + i]);
27420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
27520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("   ");
27620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
27720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf(" ");
28020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < n; ++i) {
28220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (isprint(data[offset + i])) {
28320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%c", data[offset + i]);
28420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(".");
28620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
28820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf("\n");
29020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        offset += 16;
29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huberstatic const char *FourCC2MIME(uint32_t fourcc) {
29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch (fourcc) {
29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
29818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AAC;
29920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
30118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_NB;
30220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
303371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
30418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_WB;
305371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
30620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
30718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_MPEG4;
30820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
310e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('h', '2', '6', '3'):
311e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('H', '2', '6', '3'):
31218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_H263;
31320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
31518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_AVC;
31620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
318dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(!"should not be here.");
31920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
32020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
32120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
32220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissenstatic bool AdjustChannelsAndRate(uint32_t fourcc, uint32_t *channels, uint32_t *rate) {
32448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, FourCC2MIME(fourcc))) {
32548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // AMR NB audio is always mono, 8kHz
32648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *channels = 1;
32748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *rate = 8000;
32848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return true;
32948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, FourCC2MIME(fourcc))) {
33048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // AMR WB audio is always mono, 16kHz
33148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *channels = 1;
33248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *rate = 16000;
33348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return true;
33448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
33548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    return false;
33648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen}
33748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
338693d271e62a3726689ff68f4505ba49228eb94b2Andreas HuberMPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
33905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    : mSidxDuration(0),
34005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mMoofOffset(0),
34105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mDataSource(source),
342bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber      mInitCheck(NO_INIT),
3437be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber      mHasVideo(false),
344fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen      mHeaderTimescale(0),
34520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mFirstTrack(NULL),
34672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber      mLastTrack(NULL),
347dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mFileMetaData(new MetaData),
348dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mFirstSINF(NULL),
349dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mIsDrm(false) {
35020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
35120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Extractor::~MPEG4Extractor() {
35320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
35420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
35520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        Track *next = track->next;
35620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete track;
35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = next;
35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
36020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFirstTrack = mLastTrack = NULL;
361dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
362dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    SINF *sinf = mFirstSINF;
363dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (sinf) {
364dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        SINF *next = sinf->next;
365dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        delete sinf->IPMPData;
366dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        delete sinf;
367dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf = next;
368dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
369dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    mFirstSINF = NULL;
370ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
371ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mPssh.size(); i++) {
372ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        delete [] mPssh[i].data;
373ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
37520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenuint32_t MPEG4Extractor::flags() const {
37705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return CAN_PAUSE |
37805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ((mMoofOffset == 0 || mSidxEntries.size() != 0) ?
37905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    (CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK) : 0);
38005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
38105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3827be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Hubersp<MetaData> MPEG4Extractor::getMetaData() {
3837be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    status_t err;
3847be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    if ((err = readMetaData()) != OK) {
38572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return new MetaData;
3867be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    }
3877be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
38872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return mFileMetaData;
3897be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber}
3907be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
391693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersize_t MPEG4Extractor::countTracks() {
39220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
39320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
394ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        ALOGV("MPEG4Extractor::countTracks: no tracks");
395693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return 0;
39620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
39720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
398693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    size_t n = 0;
39920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
40020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
401693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        ++n;
40220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
40320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
40420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
405ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("MPEG4Extractor::countTracks: %d tracks", n);
406693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    return n;
40720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
40820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4097e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Hubersp<MetaData> MPEG4Extractor::getTrackMetaData(
4107e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        size_t index, uint32_t flags) {
41120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
41220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
41320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return NULL;
41420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
41520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
41620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
41720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
41820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
41920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
42020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
42120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
42220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
42320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
42420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
42520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
426371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
427371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
428371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
429371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
4307e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    if ((flags & kIncludeExtensiveMetaData)
4317e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            && !track->includes_expensive_metadata) {
4327e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        track->includes_expensive_metadata = true;
4337e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
4347e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        const char *mime;
4357e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        CHECK(track->meta->findCString(kKeyMIMEType, &mime));
4367e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        if (!strncasecmp("video/", mime, 6)) {
43705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (mMoofOffset > 0) {
43805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                int64_t duration;
43905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (track->meta->findInt64(kKeyDuration, &duration)) {
44005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    // nothing fancy, just pick a frame near 1/4th of the duration
44105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    track->meta->setInt64(
44205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            kKeyThumbnailTime, duration / 4);
44305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
44405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            } else {
44505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t sampleIndex;
44605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t sampleTime;
44705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK
44805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        && track->sampleTable->getMetaDataForSample(
44905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            sampleIndex, NULL /* offset */, NULL /* size */,
45005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            &sampleTime) == OK) {
45105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    track->meta->setInt64(
45205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            kKeyThumbnailTime,
45305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            ((int64_t)sampleTime * 1000000) / track->timescale);
45405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
4557e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            }
4567e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        }
4577e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    }
4587e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
45920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return track->meta;
46020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
46120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
46248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissenstatic void MakeFourCCString(uint32_t x, char *s) {
46348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[0] = x >> 24;
46448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[1] = (x >> 16) & 0xff;
46548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[2] = (x >> 8) & 0xff;
46648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[3] = x & 0xff;
46748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[4] = '\0';
46848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen}
46948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
47020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Extractor::readMetaData() {
471bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    if (mInitCheck != NO_INIT) {
472bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        return mInitCheck;
47320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
47420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
475c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = 0;
47620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
47705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    while (true) {
47805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        err = parseChunk(&offset, 0);
47905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (err == OK) {
48005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            continue;
48105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
48205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
48305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t hdr[2];
48405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mDataSource->readAt(offset, hdr, 8) < 8) {
48505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
48605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
48705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t chunk_type = ntohl(hdr[1]);
48805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (chunk_type == FOURCC('s', 'i', 'd', 'x')) {
48905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            // parse the sidx box too
49005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            continue;
49105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
49205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            // store the offset of the first segment
49305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mMoofOffset = offset;
49405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
49505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        break;
49620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
4977be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
498bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    if (mInitCheck == OK) {
49972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        if (mHasVideo) {
500bc8b5faec8a0a9ad7c8d94945e7b000d63f0afe6Andreas Huber            mFileMetaData->setCString(
501bc8b5faec8a0a9ad7c8d94945e7b000d63f0afe6Andreas Huber                    kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG4);
50272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else {
50372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
50472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
50572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
5064678a6dc5f09008481524949a9667af5a6190374Andreas Huber        mInitCheck = OK;
507bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    } else {
508bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        mInitCheck = err;
50920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
51020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
511bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    CHECK_NE(err, (status_t)NO_INIT);
512ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
513ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // copy pssh data into file metadata
514ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int psshsize = 0;
515ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mPssh.size(); i++) {
516ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        psshsize += 20 + mPssh[i].datalen;
517ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
518ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (psshsize) {
519ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        char *buf = (char*)malloc(psshsize);
520ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        char *ptr = buf;
521ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        for (size_t i = 0; i < mPssh.size(); i++) {
522ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memcpy(ptr, mPssh[i].uuid, 20); // uuid + length
523ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memcpy(ptr + 20, mPssh[i].data, mPssh[i].datalen);
524ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ptr += (20 + mPssh[i].datalen);
525ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
526ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mFileMetaData->setData(kKeyPssh, 'pssh', buf, psshsize);
527ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        free(buf);
528ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
529bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    return mInitCheck;
53020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
53120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
532dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wangchar* MPEG4Extractor::getDrmTrackInfo(size_t trackID, int *len) {
533dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mFirstSINF == NULL) {
534dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return NULL;
535dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
536dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
537dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    SINF *sinf = mFirstSINF;
538dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (sinf && (trackID != sinf->trackID)) {
539dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf = sinf->next;
540dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
541dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
542dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (sinf == NULL) {
543dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return NULL;
544dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
545dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
546dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    *len = sinf->len;
547dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return sinf->IPMPData;
548dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
549dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
550dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang// Reads an encoded integer 7 bits at a time until it encounters the high bit clear.
55156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenstatic int32_t readSize(off64_t offset,
552dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        const sp<DataSource> DataSource, uint8_t *numOfBytes) {
553dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint32_t size = 0;
554dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t data;
555dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    bool moreData = true;
556dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    *numOfBytes = 0;
557dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
558dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (moreData) {
559dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (DataSource->readAt(offset, &data, 1) < 1) {
560dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return -1;
561dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
562dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        offset ++;
563dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        moreData = (data >= 128) ? true : false;
564dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        size = (size << 7) | (data & 0x7f); // Take last 7 bits
565dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        (*numOfBytes) ++;
566dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
567dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
568dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return size;
569dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
570dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
571c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseDrmSINF(off64_t *offset, off64_t data_offset) {
572dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t updateIdTag;
573dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
574dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
575dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
576dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset ++;
577dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
578dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (0x01/*OBJECT_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
579dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
580dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
581dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
582dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t numOfBytes;
583dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    int32_t size = readSize(data_offset, mDataSource, &numOfBytes);
584dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size < 0) {
585dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
586dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
587dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    int32_t classSize = size;
588dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset += numOfBytes;
589dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
590dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while(size >= 11 ) {
591dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t descriptorTag;
592dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, &descriptorTag, 1) < 1) {
593dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
594dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
595dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset ++;
596dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
597dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (0x11/*OBJECT_DESCRIPTOR_ID_TAG*/ != descriptorTag) {
598dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
599dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
600dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
601dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t buffer[8];
602dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        //ObjectDescriptorID and ObjectDescriptor url flag
603dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, buffer, 2) < 2) {
604dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
605dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
606dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset += 2;
607dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
608dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if ((buffer[1] >> 5) & 0x0001) { //url flag is set
609dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
610dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
611dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
612dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, buffer, 8) < 8) {
613dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
614dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
615dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset += 8;
616dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
617dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if ((0x0F/*ES_ID_REF_TAG*/ != buffer[1])
618dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                || ( 0x0A/*IPMP_DESCRIPTOR_POINTER_ID_TAG*/ != buffer[5])) {
619dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
620dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
621dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
622dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        SINF *sinf = new SINF;
623dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->trackID = U16_AT(&buffer[3]);
624dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->IPMPDescriptorID = buffer[7];
625dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->next = mFirstSINF;
626dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        mFirstSINF = sinf;
627dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
628dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        size -= (8 + 2 + 1);
629dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
630dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
631dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size != 0) {
632dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
633dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
634dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
635dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
636dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
637dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
638dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset ++;
639dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
640dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if(0x05/*IPMP_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
641dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
642dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
643dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
644dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    size = readSize(data_offset, mDataSource, &numOfBytes);
645dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size < 0) {
646dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
647dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
648dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    classSize = size;
649dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset += numOfBytes;
650dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
651dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (size > 0) {
652dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t tag;
653dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        int32_t dataLen;
654dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, &tag, 1) < 1) {
655dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
656dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
657dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset ++;
658dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
659dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (0x0B/*IPMP_DESCRIPTOR_ID_TAG*/ == tag) {
660dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            uint8_t id;
661dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            dataLen = readSize(data_offset, mDataSource, &numOfBytes);
662dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (dataLen < 0) {
663dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
664dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            } else if (dataLen < 4) {
665dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
666dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
667dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset += numOfBytes;
668dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
669dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (mDataSource->readAt(data_offset, &id, 1) < 1) {
670dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
671dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
672dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset ++;
673dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
674dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            SINF *sinf = mFirstSINF;
675dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            while (sinf && (sinf->IPMPDescriptorID != id)) {
676dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                sinf = sinf->next;
677dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
678dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (sinf == NULL) {
679dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
680dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
681dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            sinf->len = dataLen - 3;
682dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            sinf->IPMPData = new char[sinf->len];
683dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
684dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (mDataSource->readAt(data_offset + 2, sinf->IPMPData, sinf->len) < sinf->len) {
685dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
686dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
687dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset += sinf->len;
688dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
689dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size -= (dataLen + numOfBytes + 1);
690dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
691dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
692dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
693dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size != 0) {
694dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
695dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
696dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
697dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return UNKNOWN_ERROR;  // Return a dummy error.
698dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
699dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
70072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstruct PathAdder {
70172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder(Vector<uint32_t> *path, uint32_t chunkType)
70272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        : mPath(path) {
70372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        mPath->push(chunkType);
70472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
70572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
70672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    ~PathAdder() {
70772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        mPath->pop();
70872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
70972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
71072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberprivate:
71172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    Vector<uint32_t> *mPath;
71272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
71372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder(const PathAdder &);
71472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder &operator=(const PathAdder &);
71572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber};
71672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
71772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic bool underMetaDataPath(const Vector<uint32_t> &path) {
71872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return path.size() >= 5
71972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[0] == FOURCC('m', 'o', 'o', 'v')
72072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[1] == FOURCC('u', 'd', 't', 'a')
72172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[2] == FOURCC('m', 'e', 't', 'a')
72272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[3] == FOURCC('i', 'l', 's', 't');
72372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
72472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
72572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber// Given a time in seconds since Jan 1 1904, produce a human-readable string.
72672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic void convertTimeToDate(int64_t time_1904, String8 *s) {
72772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    time_t time_1970 = time_1904 - (((66 * 365 + 17) * 24) * 3600);
72872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
72972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    char tmp[32];
73072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", gmtime(&time_1970));
73172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
73272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    s->setTo(tmp);
73372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
73472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
735c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
7365d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    ALOGV("entering parseChunk %lld/%d", *offset, depth);
73720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t hdr[2];
73834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_IO;
74020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
74120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint64_t chunk_size = ntohl(hdr[0]);
74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t chunk_type = ntohl(hdr[1]);
743c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t data_offset = *offset + 8;
74420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
74520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (chunk_size == 1) {
74634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
74720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_IO;
74820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
74920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        chunk_size = ntoh64(chunk_size);
75020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        data_offset += 8;
75171b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber
75271b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        if (chunk_size < 16) {
75371b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber            // The smallest valid chunk is 16 bytes long in this case.
75471b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber            return ERROR_MALFORMED;
75571b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        }
75671b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber    } else if (chunk_size < 8) {
75771b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        // The smallest valid chunk is 8 bytes long.
75871b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        return ERROR_MALFORMED;
75920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
76020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
76120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    char chunk[5];
76220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MakeFourCCString(chunk_type, chunk);
76305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("chunk: %s @ %lld, %d", chunk, *offset, depth);
76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
76520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#if 0
76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static const char kWhitespace[] = "                                        ";
76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
76820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size);
76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    char buffer[256];
771ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    size_t n = chunk_size;
772ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    if (n > sizeof(buffer)) {
773ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        n = sizeof(buffer);
774ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    }
775ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    if (mDataSource->readAt(*offset, buffer, n)
776ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber            < (ssize_t)n) {
777ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        return ERROR_IO;
77820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
779ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
780ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    hexdump(buffer, n);
78120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#endif
78220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
78372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder autoAdder(&mPath, chunk_type);
78472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
785c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t chunk_data_size = *offset + chunk_size - data_offset;
78620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
78772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (chunk_type != FOURCC('c', 'p', 'r', 't')
788515e855eae78aa495da58356486aaa666cb57fd1James Dong            && chunk_type != FOURCC('c', 'o', 'v', 'r')
78972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            && mPath.size() == 5 && underMetaDataPath(mPath)) {
790c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t stop_offset = *offset + chunk_size;
79172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        *offset = data_offset;
79272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        while (*offset < stop_offset) {
79372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            status_t err = parseChunk(offset, depth + 1);
79472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (err != OK) {
79572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return err;
79672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
79772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
798bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
799bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (*offset != stop_offset) {
800bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
801bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
80272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
80372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return OK;
80472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
80572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
80620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch(chunk_type) {
80720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'v'):
80820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'k'):
80920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'i', 'a'):
81020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'i', 'n', 'f'):
81120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('d', 'i', 'n', 'f'):
81220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'b', 'l'):
81320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'v', 'e', 'x'):
81420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'f'):
81520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'f'):
81620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'f', 'r', 'a'):
81772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('u', 'd', 't', 'a'):
81872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('i', 'l', 's', 't'):
819ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'i', 'n', 'f'):
820ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'c', 'h', 'i'):
8210a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        case FOURCC('e', 'd', 't', 's'):
82220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
82350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
8243856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size);
82550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
826b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                if (mDataSource->flags()
827b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                        & (DataSource::kWantsPrefetching
828b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                            | DataSource::kIsCachingDataSource)) {
82950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    sp<MPEG4DataSource> cachedSource =
83050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                        new MPEG4DataSource(mDataSource);
83150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
83250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
83350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                        mDataSource = cachedSource;
83450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    }
83550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                }
8361edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber
8371edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber                mLastTrack->sampleTable = new SampleTable(mDataSource);
83850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            }
83950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
8406f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber            bool isTrack = false;
841bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (chunk_type == FOURCC('t', 'r', 'a', 'k')) {
8426f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                isTrack = true;
8436f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
844bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                Track *track = new Track;
845bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->next = NULL;
846bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                if (mLastTrack) {
847bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    mLastTrack->next = track;
848bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                } else {
849bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    mFirstTrack = track;
850bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                }
851bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                mLastTrack = track;
852bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
853bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->meta = new MetaData;
854bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->includes_expensive_metadata = false;
8556f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                track->skipTrack = false;
856bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->timescale = 0;
857bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->meta->setCString(kKeyMIMEType, "application/octet-stream");
858bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
859bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
860c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
86120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset;
86220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
86320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
86420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
86520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
86620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
86720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
86820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
869bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
870bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
871bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
872bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
8736f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber            if (isTrack) {
8746f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                if (mLastTrack->skipTrack) {
8756f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    Track *cur = mFirstTrack;
8766f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
8776f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    if (cur == mLastTrack) {
8786f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        delete cur;
8796f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        mFirstTrack = mLastTrack = NULL;
8806f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    } else {
8816f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        while (cur && cur->next != mLastTrack) {
8826f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                            cur = cur->next;
8836f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        }
8846f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        cur->next = NULL;
8856f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        delete mLastTrack;
8866f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        mLastTrack = cur;
8876f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    }
8886f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
8896f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    return OK;
8906f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                }
8916f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
892bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                status_t err = verifyTrack(mLastTrack);
893bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
894bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                if (err != OK) {
895bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    return err;
896bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                }
897bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
898bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                mInitCheck = OK;
89920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
900dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                if (!mIsDrm) {
901dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return UNKNOWN_ERROR;  // Return a dummy error.
902dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                } else {
903dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return OK;
904dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
90520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
90620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
90720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
90820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9090a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        case FOURCC('e', 'l', 's', 't'):
9100a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        {
9110a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            // See 14496-12 8.6.6
9120a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            uint8_t version;
9130a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (mDataSource->readAt(data_offset, &version, 1) < 1) {
9140a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                return ERROR_IO;
9150a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
9160a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9170a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            uint32_t entry_count;
9180a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (!mDataSource->getUInt32(data_offset + 4, &entry_count)) {
9190a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                return ERROR_IO;
9200a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
9210a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9220a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (entry_count != 1) {
9230a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                // we only support a single entry at the moment, for gapless playback
9240a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                ALOGW("ignoring edit list with %d entries", entry_count);
925fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            } else if (mHeaderTimescale == 0) {
926210efd48ed21ca0084d9440f9a1db7d9878f8094Marco Nelissen                ALOGW("ignoring edit list because timescale is 0");
9270a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            } else {
9280a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                off64_t entriesoffset = data_offset + 8;
9290a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                uint64_t segment_duration;
9300a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int64_t media_time;
9310a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9320a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                if (version == 1) {
9330a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    if (!mDataSource->getUInt64(entriesoffset, &segment_duration) ||
9340a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                            !mDataSource->getUInt64(entriesoffset + 8, (uint64_t*)&media_time)) {
9350a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        return ERROR_IO;
9360a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    }
9370a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                } else if (version == 0) {
9380a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    uint32_t sd;
9390a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int32_t mt;
9400a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    if (!mDataSource->getUInt32(entriesoffset, &sd) ||
9410a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                            !mDataSource->getUInt32(entriesoffset + 4, (uint32_t*)&mt)) {
9420a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        return ERROR_IO;
9430a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    }
9440a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    segment_duration = sd;
9450a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    media_time = mt;
9460a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                } else {
9470a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    return ERROR_IO;
9480a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                }
9490a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
950fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                uint64_t halfscale = mHeaderTimescale / 2;
951fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                segment_duration = (segment_duration * 1000000 + halfscale)/ mHeaderTimescale;
952fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                media_time = (media_time * 1000000 + halfscale) / mHeaderTimescale;
9530a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9540a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int64_t duration;
9550a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int32_t samplerate;
9560a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                if (mLastTrack->meta->findInt64(kKeyDuration, &duration) &&
9570a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        mLastTrack->meta->findInt32(kKeySampleRate, &samplerate)) {
9580a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9590a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t delay = (media_time  * samplerate + 500000) / 1000000;
9600a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
9610a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9620a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t paddingus = duration - (segment_duration + media_time);
963be1195a6d5e6dd4299da344cf9905dd6a12dc4efMarco Nelissen                    if (paddingus < 0) {
964be1195a6d5e6dd4299da344cf9905dd6a12dc4efMarco Nelissen                        // track duration from media header (which is what kKeyDuration is) might
965be1195a6d5e6dd4299da344cf9905dd6a12dc4efMarco Nelissen                        // be slightly shorter than the segment duration, which would make the
966be1195a6d5e6dd4299da344cf9905dd6a12dc4efMarco Nelissen                        // padding negative. Clamp to zero.
967be1195a6d5e6dd4299da344cf9905dd6a12dc4efMarco Nelissen                        paddingus = 0;
968be1195a6d5e6dd4299da344cf9905dd6a12dc4efMarco Nelissen                    }
9690a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t paddingsamples = (paddingus * samplerate + 500000) / 1000000;
9700a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    mLastTrack->meta->setInt32(kKeyEncoderPadding, paddingsamples);
9710a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                }
9720a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
9730a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            *offset += chunk_size;
9740a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            break;
9750a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        }
9760a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
977ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('f', 'r', 'm', 'a'):
978ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
97948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t original_fourcc;
980ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset, &original_fourcc, 4) < 4) {
981ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
982ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
983ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            original_fourcc = ntohl(original_fourcc);
984ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("read original format: %d", original_fourcc);
985ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc));
98648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t num_channels = 0;
98748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t sample_rate = 0;
98848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (AdjustChannelsAndRate(original_fourcc, &num_channels, &sample_rate)) {
98948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
99048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
99148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            }
992ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
993ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
994ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
995ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
996ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('t', 'e', 'n', 'c'):
997ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
998ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (chunk_size < 32) {
999ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1000ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1001ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1002ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // tenc box contains 1 byte version, 3 byte flags, 3 byte default algorithm id, one byte
1003ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // default IV size, 16 bytes default KeyID
1004ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // (ISO 23001-7)
1005ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            char buf[4];
1006ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memset(buf, 0, 4);
1007ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 4, buf + 1, 3) < 3) {
1008ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1009ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1010ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t defaultAlgorithmId = ntohl(*((int32_t*)buf));
1011ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (defaultAlgorithmId > 1) {
1012ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only 0 (clear) and 1 (AES-128) are valid
1013ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1014ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1015ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1016ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memset(buf, 0, 4);
1017ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 7, buf + 3, 1) < 1) {
1018ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1019ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1020ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t defaultIVSize = ntohl(*((int32_t*)buf));
1021ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1022ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((defaultAlgorithmId == 0 && defaultIVSize != 0) ||
1023ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    (defaultAlgorithmId != 0 && defaultIVSize == 0)) {
1024ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only unencrypted data must have 0 IV size
1025ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1026ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            } else if (defaultIVSize != 0 &&
1027ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    defaultIVSize != 8 &&
1028ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    defaultIVSize != 16) {
1029ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only supported sizes are 0, 8 and 16
1030ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1031ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1032ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1033ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint8_t defaultKeyId[16];
1034ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1035ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 8, &defaultKeyId, 16) < 16) {
1036ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1037ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1038ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1039ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setInt32(kKeyCryptoMode, defaultAlgorithmId);
1040ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setInt32(kKeyCryptoDefaultIVSize, defaultIVSize);
1041ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setData(kKeyCryptoKey, 'tenc', defaultKeyId, 16);
1042ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
1043ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1044ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1045ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
104620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'k', 'h', 'd'):
104720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1048ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            status_t err;
1049ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) {
1050ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber                return err;
105120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
105220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
105320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
105420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
105520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
105620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1057ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('p', 's', 's', 'h'):
1058ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
1059ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            PsshInfo pssh;
1060ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1061ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 4, &pssh.uuid, 16) < 16) {
1062ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1063ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1064ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1065ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t psshdatalen = 0;
1066ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 20, &psshdatalen, 4) < 4) {
1067ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1068ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1069ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            pssh.datalen = ntohl(psshdatalen);
1070ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("pssh data size: %d", pssh.datalen);
1071ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (pssh.datalen + 20 > chunk_size) {
1072ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // pssh data length exceeds size of containing box
1073ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1074ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1075ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1076ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            pssh.data = new uint8_t[pssh.datalen];
1077ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("allocated pssh @ %p", pssh.data);
1078ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ssize_t requested = (ssize_t) pssh.datalen;
1079ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 24, pssh.data, requested) < requested) {
1080ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1081ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1082ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mPssh.push_back(pssh);
1083ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1084ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
1085ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1086ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1087ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
108820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'h', 'd'):
108920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
109020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
109120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
109220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
109320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
109420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t version;
109534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
109620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, &version, sizeof(version))
109720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(version)) {
109820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
109920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
110020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1101c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t timescale_offset;
110220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
110320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
110420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 16;
110520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else if (version == 0) {
110620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 8;
110720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
110820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
110920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
111020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
111120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t timescale;
111234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
111320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        timescale_offset, &timescale, sizeof(timescale))
111420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(timescale)) {
111520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
111620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
111720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
111820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->timescale = ntohl(timescale);
111920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
112005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            int64_t duration = 0;
112120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
112234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
112320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration, sizeof(duration))
112420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration)) {
112520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
112620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
112720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = ntoh64(duration);
112820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
112905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t duration32;
113034769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
113120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration32, sizeof(duration32))
113220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration32)) {
113320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
113420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
113505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // ffmpeg sets duration to -1, which is incorrect.
113605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (duration32 != 0xffffffff) {
113705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    duration = ntohl(duration32);
113805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
113920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
114048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mLastTrack->meta->setInt64(
114148c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                    kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
114220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11437a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            uint8_t lang[2];
11447a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            off64_t lang_offset;
11457a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            if (version == 1) {
11467a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                lang_offset = timescale_offset + 4 + 8;
11477a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            } else if (version == 0) {
11487a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                lang_offset = timescale_offset + 4 + 4;
11497a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            } else {
11507a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                return ERROR_IO;
11517a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            }
11527a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
11537a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            if (mDataSource->readAt(lang_offset, &lang, sizeof(lang))
11547a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                    < (ssize_t)sizeof(lang)) {
11557a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                return ERROR_IO;
11567a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            }
11577a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
11587a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // To get the ISO-639-2/T three character language code
11597a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // 1 bit pad followed by 3 5-bits characters. Each character
11607a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // is packed as the difference between its ASCII value and 0x60.
11617a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            char lang_code[4];
11627a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[0] = ((lang[0] >> 2) & 0x1f) + 0x60;
11637a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[1] = ((lang[0] & 0x3) << 3 | (lang[1] >> 5)) + 0x60;
11647a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[2] = (lang[1] & 0x1f) + 0x60;
11657a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[3] = '\0';
11667a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
11677a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            mLastTrack->meta->setCString(
11687a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                    kKeyMediaLanguage, lang_code);
11697a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
117020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
117120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
117220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
117320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
117420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'd'):
117520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
117620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 8) {
117720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
117820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
117920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8];
1181c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size < (off64_t)sizeof(buffer)) {
1182bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1183bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
1184bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
118534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
118620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, 8) < 8) {
118720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
118820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
118920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
119020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
119120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
119220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
119320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
119420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
119520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t entry_count = U32_AT(&buffer[4]);
119620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
119720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (entry_count > 1) {
11983b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // For 3GPP timed text, there could be multiple tx3g boxes contain
11993b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // multiple text display formats. These formats will be used to
12003b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // display the timed text.
1201ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // For encrypted files, there may also be more than one entry.
12023b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                const char *mime;
12033b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1204ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) &&
1205ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                        strcasecmp(mime, "application/octet-stream")) {
12063b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    // For now we only support a single type of media per track.
12073b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    mLastTrack->skipTrack = true;
12083b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    *offset += chunk_size;
12093b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    break;
12103b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                }
121120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1212c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
121320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + 8;
121420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            for (uint32_t i = 0; i < entry_count; ++i) {
121520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
121620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
121720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
121820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
121920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1220bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1221bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1222bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1223bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
122420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
122520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
122620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
122720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
122848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        case FOURCC('e', 'n', 'c', 'a'):
122920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
1230371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
123120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
123220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8 + 20];
123320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
123420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic AudioSampleEntry size.
123520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
123620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
123720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
123834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
123920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
124020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
124120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
124220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
124320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
124448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t num_channels = U16_AT(&buffer[16]);
124520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
124681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint16_t sample_size = U16_AT(&buffer[18]);
124781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
124881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
124948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (chunk_type != FOURCC('e', 'n', 'c', 'a')) {
125048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                // if the chunk type is enca, we'll get the type from the sinf/frma box later
125148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
125248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate);
125320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
125448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            ALOGV("*** coding='%s' %d channels, size %d, rate %d\n",
125581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                   chunk, num_channels, sample_size, sample_rate);
125620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
125720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
125820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1259c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
126020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
126120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
126220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
126320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
126420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
126520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
126620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1267bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1268bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1269bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1270bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
127120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
127220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
127320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
127420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
1275ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('e', 'n', 'c', 'v'):
127620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
1277e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('H', '2', '6', '3'):
1278e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('h', '2', '6', '3'):
127920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
128020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
12817be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber            mHasVideo = true;
12827be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
128320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[78];
128420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
128520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic VideoSampleEntry size.
128620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
128720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
128820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
128934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
129020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
129120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
129220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
129320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
129420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
129520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t width = U16_AT(&buffer[6 + 18]);
129620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t height = U16_AT(&buffer[6 + 20]);
129720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1298ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // The video sample is not standard-compliant if it has invalid dimension.
1299a6256238d9015c42129fe43791968768fe501efaJames Dong            // Use some default width and height value, and
1300a6256238d9015c42129fe43791968768fe501efaJames Dong            // let the decoder figure out the actual width and height (and thus
1301a6256238d9015c42129fe43791968768fe501efaJames Dong            // be prepared for INFO_FOMRAT_CHANGED event).
1302a6256238d9015c42129fe43791968768fe501efaJames Dong            if (width == 0)  width  = 352;
1303a6256238d9015c42129fe43791968768fe501efaJames Dong            if (height == 0) height = 288;
1304a6256238d9015c42129fe43791968768fe501efaJames Dong
1305134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            // printf("*** coding='%s' width=%d height=%d\n",
1306134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            //        chunk, width, height);
130720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1308ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (chunk_type != FOURCC('e', 'n', 'c', 'v')) {
1309ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // if the chunk type is encv, we'll get the type from the sinf/frma box later
1310ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
1311ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
131220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyWidth, width);
131320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyHeight, height);
131420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1315c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
131620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
131720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
131820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
131920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
132020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
132120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
132220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1323bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1324bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1325bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1326bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
132720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
132820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
132920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
133020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'c', 'o'):
133120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('c', 'o', '6', '4'):
133220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
133320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
133420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setChunkOffsetParams(
133520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
133620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
133720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
133820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
133920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
134020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
134120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
134220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
134320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
134420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
134520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'c'):
134620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
134720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
134820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleToChunkParams(
134920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
135020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
135120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
135220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
135320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
135420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
135520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
135720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
135820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
135920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'z'):
136020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'z', '2'):
136120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
136220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
136320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleSizeParams(
136420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
136520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
136620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
136720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
136820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
136920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1370738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            size_t max_size;
137149110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            err = mLastTrack->sampleTable->getMaxSampleSize(&max_size);
137249110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber
137349110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            if (err != OK) {
137449110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber                return err;
137549110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            }
1376738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber
137705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (max_size != 0) {
137805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // Assume that a given buffer only contains at most 10 chunks,
137905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // each chunk originally prefixed with a 2 byte length will
138005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
138105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // and thus will grow by 2 bytes per chunk.
138205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
138305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            } else {
138405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // No size was specified. Pick a conservatively large size.
138505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                int32_t width, height;
1386f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                if (!mLastTrack->meta->findInt32(kKeyWidth, &width) ||
1387f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    !mLastTrack->meta->findInt32(kKeyHeight, &height)) {
138805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ALOGE("No width or height, assuming worst case 1080p");
1389f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    width = 1920;
1390f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    height = 1080;
139105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
1392f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar
13934256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen                const char *mime;
13944256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1395f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
1396f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // AVC requires compression ratio of at least 2, and uses
1397f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // macroblocks
1398f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    max_size = ((width + 15) / 16) * ((height + 15) / 16) * 192;
1399f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                } else {
1400f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // For all other formats there is no minimum compression
1401f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // ratio. Use compression ratio of 1.
1402f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    max_size = width * height * 3 / 2;
1403f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                }
1404f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size);
140505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
140620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
1407113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong
14084256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            // NOTE: setting another piece of metadata invalidates any pointers (such as the
14094256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            // mimetype) previously obtained, so don't cache them.
14104256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            const char *mime;
14114256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1412113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            // Calculate average frame rate.
1413113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            if (!strncasecmp("video/", mime, 6)) {
1414113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                size_t nSamples = mLastTrack->sampleTable->countSamples();
1415113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                int64_t durationUs;
1416113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                if (mLastTrack->meta->findInt64(kKeyDuration, &durationUs)) {
1417113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                    if (durationUs > 0) {
1418113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                        int32_t frameRate = (nSamples * 1000000LL +
1419113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                                    (durationUs >> 1)) / durationUs;
1420113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                        mLastTrack->meta->setInt32(kKeyFrameRate, frameRate);
1421113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                    }
1422113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                }
1423113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            }
1424113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong
142520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
142620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
142720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
142820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 't', 's'):
142920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
143020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
143120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setTimeToSampleParams(
143220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
143320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
143420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
143520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
143620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
143720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
143820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
143920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
144020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
144120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14424931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        case FOURCC('c', 't', 't', 's'):
14434931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        {
14444931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            status_t err =
14454931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                mLastTrack->sampleTable->setCompositionTimeToSampleParams(
14464931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                        data_offset, chunk_data_size);
14474931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
14484931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            if (err != OK) {
14494931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                return err;
14504931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            }
14514931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
14524931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            *offset += chunk_size;
14534931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            break;
14544931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        }
14554931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
145620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 's'):
145720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
145820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
145920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSyncSampleParams(
146020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
146120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
146220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
146320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
146420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
146520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
146620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
146720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
146820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
146920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14704948818cb91176df74c972ac27b2f392b5d148bcJames Dong        // @xyz
14714948818cb91176df74c972ac27b2f392b5d148bcJames Dong        case FOURCC('\xA9', 'x', 'y', 'z'):
14724948818cb91176df74c972ac27b2f392b5d148bcJames Dong        {
14734948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Best case the total data length inside "@xyz" box
14744948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // would be 8, for instance "@xyz" + "\x00\x04\x15\xc7" + "0+0/",
14754948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // where "\x00\x04" is the text string length with value = 4,
14764948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // "\0x15\xc7" is the language code = en, and "0+0" is a
14774948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // location (string) value with longitude = 0 and latitude = 0.
14784948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (chunk_data_size < 8) {
14794948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_MALFORMED;
14804948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
14814948818cb91176df74c972ac27b2f392b5d148bcJames Dong
14824948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Worst case the location string length would be 18,
14834948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // for instance +90.0000-180.0000, without the trailing "/" and
14844948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // the string length + language code.
14854948818cb91176df74c972ac27b2f392b5d148bcJames Dong            char buffer[18];
14864948818cb91176df74c972ac27b2f392b5d148bcJames Dong
14874948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Substracting 5 from the data size is because the text string length +
14884948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // language code takes 4 bytes, and the trailing slash "/" takes 1 byte.
14894948818cb91176df74c972ac27b2f392b5d148bcJames Dong            off64_t location_length = chunk_data_size - 5;
14904948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (location_length >= (off64_t) sizeof(buffer)) {
14914948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_MALFORMED;
14924948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
14934948818cb91176df74c972ac27b2f392b5d148bcJames Dong
14944948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (mDataSource->readAt(
14954948818cb91176df74c972ac27b2f392b5d148bcJames Dong                        data_offset + 4, buffer, location_length) < location_length) {
14964948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_IO;
14974948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
14984948818cb91176df74c972ac27b2f392b5d148bcJames Dong
14994948818cb91176df74c972ac27b2f392b5d148bcJames Dong            buffer[location_length] = '\0';
15004948818cb91176df74c972ac27b2f392b5d148bcJames Dong            mFileMetaData->setCString(kKeyLocation, buffer);
15014948818cb91176df74c972ac27b2f392b5d148bcJames Dong            *offset += chunk_size;
15024948818cb91176df74c972ac27b2f392b5d148bcJames Dong            break;
15034948818cb91176df74c972ac27b2f392b5d148bcJames Dong        }
15044948818cb91176df74c972ac27b2f392b5d148bcJames Dong
150520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('e', 's', 'd', 's'):
150620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
150720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
150820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
150920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
151020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
151120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[256];
1512c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size > (off64_t)sizeof(buffer)) {
151320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
151420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
151520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
151634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
151720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
151820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
151920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
152020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
152120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
152220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
152320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
152420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
152520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
152620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
152720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
152820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1529ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            if (mPath.size() >= 2
1530ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
1531ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // Information from the ESDS must be relied on for proper
1532ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // setup of sample rate and channel count for MPEG4 Audio.
1533ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // The generic header appears to only contain generic
1534ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // information...
1535ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1536ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio(
1537ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                        &buffer[4], chunk_data_size - 4);
1538ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1539ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                if (err != OK) {
1540ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    return err;
1541ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                }
1542ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            }
1543ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
154420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
154520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
154620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
154720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
154820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', 'C'):
154920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1550d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson            sp<ABuffer> buffer = new ABuffer(chunk_data_size);
155120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
155234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
1553d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson                        data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
155420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
155520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
155620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
155720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
1558d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson                    kKeyAVCC, kTypeAVCC, buffer->data(), chunk_data_size);
155920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
156020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
156120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
156220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
156320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1564244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        case FOURCC('d', '2', '6', '3'):
1565244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        {
156617e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            /*
156717e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * d263 contains a fixed 7 bytes part:
156817e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   vendor - 4 bytes
156917e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   version - 1 byte
157017e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   level - 1 byte
157117e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   profile - 1 byte
157217e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * optionally, "d263" box itself may contain a 16-byte
157317e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * bit rate box (bitr)
157417e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   average bit rate - 4 bytes
157517e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   max bit rate - 4 bytes
157617e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             */
157717e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            char buffer[23];
157817e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            if (chunk_data_size != 7 &&
157917e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong                chunk_data_size != 23) {
158029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Incorrect D263 box size %lld", chunk_data_size);
1581244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                return ERROR_MALFORMED;
1582244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            }
1583244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1584244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            if (mDataSource->readAt(
1585244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                    data_offset, buffer, chunk_data_size) < chunk_data_size) {
1586244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                return ERROR_IO;
1587244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            }
1588244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1589244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size);
1590244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1591244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            *offset += chunk_size;
1592244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            break;
1593244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        }
1594244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
159572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'e', 't', 'a'):
159672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
159772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            uint8_t buffer[4];
1598c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size < (off64_t)sizeof(buffer)) {
1599bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1600bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
1601bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
160272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
160372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, buffer, 4) < 4) {
160472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
160572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
160672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
160772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (U32_AT(buffer) != 0) {
160872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                // Should be version 0, flags 0.
1609ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
1610ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // If it's not, let's assume this is one of those
1611ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // apparently malformed chunks that don't have flags
1612ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // and completely different semantics than what's
1613ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // in the MPEG4 specs and skip it.
1614ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                *offset += chunk_size;
1615ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                return OK;
161672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
161772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1618c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
161972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset = data_offset + sizeof(buffer);
162072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            while (*offset < stop_offset) {
162172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                status_t err = parseChunk(offset, depth + 1);
162272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
162372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
162472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
162572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
1626bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1627bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1628bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1629bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
163072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
163172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
163272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
16335d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('m', 'e', 'a', 'n'):
16345d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('n', 'a', 'm', 'e'):
163572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('d', 'a', 't', 'a'):
163672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
163772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mPath.size() == 6 && underMetaDataPath(mPath)) {
163872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                status_t err = parseMetaData(data_offset, chunk_data_size);
163972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
164072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
164172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
164272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
164372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
164472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
164572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset += chunk_size;
164672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
164772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
164872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
164972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'v', 'h', 'd'):
165072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
1651fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            if (chunk_data_size < 24) {
165272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_MALFORMED;
165372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
165472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1655fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            uint8_t header[24];
165672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
165772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, header, sizeof(header))
165872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    < (ssize_t)sizeof(header)) {
165972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
166072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
166172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1662fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            uint64_t creationTime;
166372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (header[0] == 1) {
166472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U64_AT(&header[4]);
1665fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                mHeaderTimescale = U32_AT(&header[20]);
1666bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (header[0] != 0) {
1667bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
166872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            } else {
166972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U32_AT(&header[4]);
1670fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                mHeaderTimescale = U32_AT(&header[12]);
167172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
167272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
167372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            String8 s;
167472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            convertTimeToDate(creationTime, &s);
167572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
167672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(kKeyDate, s.string());
167772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
167872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset += chunk_size;
167972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
168072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
168172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1682dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        case FOURCC('m', 'd', 'a', 't'):
1683dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        {
1684ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("mdat chunk, drm: %d", mIsDrm);
1685dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (!mIsDrm) {
1686dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                *offset += chunk_size;
1687dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                break;
1688dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
1689dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
1690dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (chunk_size < 8) {
1691dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
1692dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
1693dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
1694dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return parseDrmSINF(offset, data_offset);
1695dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
1696dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
16973b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        case FOURCC('h', 'd', 'l', 'r'):
16983b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        {
16993b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t buffer;
17003b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (mDataSource->readAt(
17013b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                        data_offset + 8, &buffer, 4) < 4) {
17023b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_IO;
17033b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17043b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17053b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type = ntohl(buffer);
17063b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            // For the 3GPP file format, the handler-type within the 'hdlr' box
1707e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            // shall be 'text'. We also want to support 'sbtl' handler type
1708e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            // for a practical reason as various MPEG4 containers use it.
1709e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            if (type == FOURCC('t', 'e', 'x', 't') || type == FOURCC('s', 'b', 't', 'l')) {
17103b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
17113b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17123b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17133b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            *offset += chunk_size;
17143b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            break;
17153b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        }
17163b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17177a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        case FOURCC('t', 'x', '3', 'g'):
17187a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        {
17193b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type;
17203b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            const void *data;
17213b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            size_t size = 0;
17223b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (!mLastTrack->meta->findData(
17233b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    kKeyTextFormatData, &type, &data, &size)) {
17243b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                size = 0;
17253b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17263b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
1727e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake            if (SIZE_MAX - chunk_size <= size) {
1728e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake                return ERROR_MALFORMED;
1729e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake            }
1730e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake
17313b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint8_t *buffer = new uint8_t[size + chunk_size];
1732e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake            if (buffer == NULL) {
1733e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake                return ERROR_MALFORMED;
1734e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake            }
17353b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17363b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (size > 0) {
17373b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                memcpy(buffer, data, size);
17383b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17393b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17403b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size))
17413b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    < chunk_size) {
17423b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                delete[] buffer;
17433b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                buffer = NULL;
17443b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17453b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_IO;
17463b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17473b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17483b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            mLastTrack->meta->setData(
17493b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    kKeyTextFormatData, 0, buffer, size + chunk_size);
17503b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17513b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            delete[] buffer;
17527a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
17537a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            *offset += chunk_size;
17547a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            break;
17557a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        }
17567a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
1757515e855eae78aa495da58356486aaa666cb57fd1James Dong        case FOURCC('c', 'o', 'v', 'r'):
1758515e855eae78aa495da58356486aaa666cb57fd1James Dong        {
1759515e855eae78aa495da58356486aaa666cb57fd1James Dong            if (mFileMetaData != NULL) {
17603856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("chunk_data_size = %lld and data_offset = %lld",
1761515e855eae78aa495da58356486aaa666cb57fd1James Dong                        chunk_data_size, data_offset);
176205ddc499b9d50c90f552ed1333110f28a1406e7cJoshua J. Drake
176305ddc499b9d50c90f552ed1333110f28a1406e7cJoshua J. Drake                if (chunk_data_size >= SIZE_MAX - 1) {
176405ddc499b9d50c90f552ed1333110f28a1406e7cJoshua J. Drake                    return ERROR_MALFORMED;
176505ddc499b9d50c90f552ed1333110f28a1406e7cJoshua J. Drake                }
17661552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1);
1767515e855eae78aa495da58356486aaa666cb57fd1James Dong                if (mDataSource->readAt(
17681552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                    data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) {
1769515e855eae78aa495da58356486aaa666cb57fd1James Dong                    return ERROR_IO;
1770515e855eae78aa495da58356486aaa666cb57fd1James Dong                }
1771515e855eae78aa495da58356486aaa666cb57fd1James Dong                const int kSkipBytesOfDataBox = 16;
17724a492bf2ac47b9844d2527e1fcdf0064c3d8d52eJoshua J. Drake                if (chunk_data_size <= kSkipBytesOfDataBox) {
17734a492bf2ac47b9844d2527e1fcdf0064c3d8d52eJoshua J. Drake                    return ERROR_MALFORMED;
17744a492bf2ac47b9844d2527e1fcdf0064c3d8d52eJoshua J. Drake                }
17754a492bf2ac47b9844d2527e1fcdf0064c3d8d52eJoshua J. Drake
1776515e855eae78aa495da58356486aaa666cb57fd1James Dong                mFileMetaData->setData(
1777515e855eae78aa495da58356486aaa666cb57fd1James Dong                    kKeyAlbumArt, MetaData::TYPE_NONE,
17781552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                    buffer->data() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox);
1779515e855eae78aa495da58356486aaa666cb57fd1James Dong            }
1780515e855eae78aa495da58356486aaa666cb57fd1James Dong
1781515e855eae78aa495da58356486aaa666cb57fd1James Dong            *offset += chunk_size;
1782515e855eae78aa495da58356486aaa666cb57fd1James Dong            break;
1783515e855eae78aa495da58356486aaa666cb57fd1James Dong        }
1784515e855eae78aa495da58356486aaa666cb57fd1James Dong
17855d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('-', '-', '-', '-'):
17865d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        {
17875d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentMean.clear();
17885d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentName.clear();
17895d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentData.clear();
17905d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            *offset += chunk_size;
17915d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            break;
17925d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        }
17935d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen
179405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('s', 'i', 'd', 'x'):
179505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        {
179605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            parseSegmentIndex(data_offset, chunk_data_size);
179705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset += chunk_size;
179805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return UNKNOWN_ERROR; // stop parsing after sidx
179905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
180005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
180120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
180220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
180320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
180420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
180520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
180620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
180720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
180820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
180920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
181020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
181105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) {
181205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen  ALOGV("MPEG4Extractor::parseSegmentIndex");
181305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
181405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 12) {
181505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      return -EINVAL;
181605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
181705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
181805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
181905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) {
182005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
182105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
182205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
182305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t version = flags >> 24;
182405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    flags &= 0xffffff;
182505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
182605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx version %d", version);
182705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
182805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t referenceId;
182905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, &referenceId)) {
183005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
183105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
183205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
183305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t timeScale;
183405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 8, &timeScale)) {
183505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
183605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
183705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx refid/timescale: %d/%d", referenceId, timeScale);
183805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
183905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t earliestPresentationTime;
184005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t firstOffset;
184105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
184205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 12;
184305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 12;
184405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
184505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (version == 0) {
184605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 8) {
184705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
184805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
184905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t tmp;
185005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
185105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
185205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
185305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        earliestPresentationTime = tmp;
185405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset + 4, &tmp)) {
185505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
185605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
185705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        firstOffset = tmp;
185805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 8;
185905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 8;
186005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
186105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 16) {
186205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
186305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
186405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset, &earliestPresentationTime)) {
186505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
186605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
186705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset + 8, &firstOffset)) {
186805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
186905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
187005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 16;
187105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 16;
187205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
187305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx pres/off: %Ld/%Ld", earliestPresentationTime, firstOffset);
187405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
187505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 4) {
187605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
187705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
187805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
187905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint16_t referenceCount;
188005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt16(offset + 2, &referenceCount)) {
188105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
188205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
188305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 4;
188405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 4;
188505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("refcount: %d", referenceCount);
188605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
188705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < referenceCount * 12) {
188805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
188905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
189005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
189105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t total_duration = 0;
189205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    for (unsigned int i = 0; i < referenceCount; i++) {
189305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t d1, d2, d3;
189405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
189505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &d1) ||     // size
189605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            !mDataSource->getUInt32(offset + 4, &d2) || // duration
189705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            !mDataSource->getUInt32(offset + 8, &d3)) { // flags
189805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
189905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
190005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
190105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (d1 & 0x80000000) {
190205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGW("sub-sidx boxes not supported yet");
190305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
190405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool sap = d3 & 0x80000000;
190505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool saptype = d3 >> 28;
190605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!sap || saptype > 2) {
190705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGW("not a stream access point, or unsupported type");
190805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
190905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        total_duration += d2;
191005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 12;
191105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV(" item %d, %08x %08x %08x", i, d1, d2, d3);
191205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        SidxEntry se;
191305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        se.mSize = d1 & 0x7fffffff;
191405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        se.mDurationUs = 1000000LL * d2 / timeScale;
191505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mSidxEntries.add(se);
191605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
191705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
191805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mSidxDuration = total_duration * 1000000 / timeScale;
191905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("duration: %lld", mSidxDuration);
192005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
192105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t metaDuration;
192205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mLastTrack->meta->findInt64(kKeyDuration, &metaDuration) || metaDuration == 0) {
192305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mLastTrack->meta->setInt64(kKeyDuration, mSidxDuration);
192405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
192505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
192605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
192705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
192805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
192905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
1930ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huberstatus_t MPEG4Extractor::parseTrackHeader(
1931c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t data_offset, off64_t data_size) {
1932ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (data_size < 4) {
1933ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_MALFORMED;
1934ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1935ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1936ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint8_t version;
1937ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (mDataSource->readAt(data_offset, &version, 1) < 1) {
1938ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_IO;
1939ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1940ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1941ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    size_t dynSize = (version == 1) ? 36 : 24;
1942ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1943ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint8_t buffer[36 + 60];
1944ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1945c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    if (data_size != (off64_t)dynSize + 60) {
1946ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_MALFORMED;
1947ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1948ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1949ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (mDataSource->readAt(
1950ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber                data_offset, buffer, data_size) < (ssize_t)data_size) {
1951ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_IO;
1952ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1953ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1954ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint64_t ctime, mtime, duration;
1955ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t id;
1956ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1957ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (version == 1) {
1958ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        ctime = U64_AT(&buffer[4]);
1959ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mtime = U64_AT(&buffer[12]);
1960ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        id = U32_AT(&buffer[20]);
1961ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        duration = U64_AT(&buffer[28]);
196204022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen    } else if (version == 0) {
1963ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        ctime = U32_AT(&buffer[4]);
1964ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mtime = U32_AT(&buffer[8]);
1965ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        id = U32_AT(&buffer[12]);
1966ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        duration = U32_AT(&buffer[20]);
196704022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen    } else {
196804022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen        return ERROR_UNSUPPORTED;
1969ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1970ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1971ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    mLastTrack->meta->setInt32(kKeyTrackID, id);
1972ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1973ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    size_t matrixOffset = dynSize + 16;
1974ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a00 = U32_AT(&buffer[matrixOffset]);
1975ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a01 = U32_AT(&buffer[matrixOffset + 4]);
1976ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t dx = U32_AT(&buffer[matrixOffset + 8]);
1977ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a10 = U32_AT(&buffer[matrixOffset + 12]);
1978ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a11 = U32_AT(&buffer[matrixOffset + 16]);
1979ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t dy = U32_AT(&buffer[matrixOffset + 20]);
1980ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1981ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#if 0
1982df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("x' = %.2f * x + %.2f * y + %.2f",
1983ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber         a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f);
1984df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("y' = %.2f * x + %.2f * y + %.2f",
1985ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber         a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f);
1986ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#endif
1987ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1988ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t rotationDegrees;
1989ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1990ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    static const int32_t kFixedOne = 0x10000;
1991ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) {
1992ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        // Identity, no rotation
1993ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 0;
1994ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) {
1995ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 90;
1996ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) {
1997ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 270;
1998ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) {
1999ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 180;
2000ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else {
20015ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("We only support 0,90,180,270 degree rotation matrices");
2002ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 0;
2003ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2004ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2005ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (rotationDegrees != 0) {
2006ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees);
2007ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2008ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2009b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    // Handle presentation display size, which could be different
2010b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    // from the image size indicated by kKeyWidth and kKeyHeight.
2011ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t width = U32_AT(&buffer[dynSize + 52]);
2012ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t height = U32_AT(&buffer[dynSize + 56]);
2013b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    mLastTrack->meta->setInt32(kKeyDisplayWidth, width >> 16);
2014b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    mLastTrack->meta->setInt32(kKeyDisplayHeight, height >> 16);
2015ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2016ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    return OK;
2017ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber}
2018ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2019c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseMetaData(off64_t offset, size_t size) {
202072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (size < 4) {
202172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_MALFORMED;
202272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
202372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
202472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint8_t *buffer = new uint8_t[size + 1];
202572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (mDataSource->readAt(
202672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                offset, buffer, size) != (ssize_t)size) {
202772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        delete[] buffer;
202872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        buffer = NULL;
202972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
203072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_IO;
203172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
203272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
203372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t flags = U32_AT(buffer);
203472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
203572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t metadataKey = 0;
20365d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    char chunk[5];
20375d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    MakeFourCCString(mPath[4], chunk);
20385d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    ALOGV("meta: %s @ %lld", chunk, offset);
203972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    switch (mPath[4]) {
204072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'a', 'l', 'b'):
204172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
204272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbum;
204372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
204472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
204572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'A', 'R', 'T'):
204672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
204772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyArtist;
204872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
204972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
205066ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        case FOURCC('a', 'A', 'R', 'T'):
205166ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        {
205266ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            metadataKey = kKeyAlbumArtist;
205366ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            break;
205466ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        }
205572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'd', 'a', 'y'):
205672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
205772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyYear;
205872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
205972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
206072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'n', 'a', 'm'):
206172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
206272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyTitle;
206372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
206472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
206572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'w', 'r', 't'):
206672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
206772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyWriter;
206872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
206972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
207072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('c', 'o', 'v', 'r'):
207172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
207272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbumArt;
207372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
207472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
207572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('g', 'n', 'r', 'e'):
207672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
207772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyGenre;
207872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
207972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
208026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC(0xa9, 'g', 'e', 'n'):
208126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
208226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            metadataKey = kKeyGenre;
208326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
208426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
208511f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        case FOURCC('c', 'p', 'i', 'l'):
208611f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        {
208711f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            if (size == 9 && flags == 21) {
208811f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                char tmp[16];
208911f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                sprintf(tmp, "%d",
209011f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                        (int)buffer[size - 1]);
209111f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen
209211f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                mFileMetaData->setCString(kKeyCompilation, tmp);
209311f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            }
209411f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            break;
209511f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        }
209672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('t', 'r', 'k', 'n'):
209772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
209872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (size == 16 && flags == 0) {
209972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char tmp[16];
2100afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTrack = (uint16_t*)&buffer[10];
2101afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTotalTracks = (uint16_t*)&buffer[12];
2102afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                sprintf(tmp, "%d/%d", ntohs(*pTrack), ntohs(*pTotalTracks));
210372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
210472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
210572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
210672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
210772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
210826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC('d', 'i', 's', 'k'):
210926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
2110afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik            if ((size == 14 || size == 16) && flags == 0) {
211126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                char tmp[16];
2112afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pDisc = (uint16_t*)&buffer[10];
2113afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTotalDiscs = (uint16_t*)&buffer[12];
2114afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                sprintf(tmp, "%d/%d", ntohs(*pDisc), ntohs(*pTotalDiscs));
211526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
211626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(kKeyDiscNumber, tmp);
211726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            }
211826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
211926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
21205d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('-', '-', '-', '-'):
21215d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        {
21225d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            buffer[size] = '\0';
21235d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            switch (mPath[5]) {
21245d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('m', 'e', 'a', 'n'):
21255d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentMean.setTo((const char *)buffer + 4);
21265d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
21275d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('n', 'a', 'm', 'e'):
21285d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentName.setTo((const char *)buffer + 4);
21295d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
21305d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('d', 'a', 't', 'a'):
21315d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentData.setTo((const char *)buffer + 8);
21325d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
21335d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            }
21348c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
21358c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // Once we have a set of mean/name/data info, go ahead and process
21368c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // it to see if its something we are interested in.  Whether or not
21378c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // were are interested in the specific tag, make sure to clear out
21388c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // the set so we can be ready to process another tuple should one
21398c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // show up later in the file.
21408c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            if ((mLastCommentMean.length() != 0) &&
21418c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                (mLastCommentName.length() != 0) &&
21428c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                (mLastCommentData.length() != 0)) {
21438c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
21448c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                if (mLastCommentMean == "com.apple.iTunes"
21458c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        && mLastCommentName == "iTunSMPB") {
21468c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    int32_t delay, padding;
21478c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    if (sscanf(mLastCommentData,
21488c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                               " %*x %x %x %*x", &delay, &padding) == 2) {
21498c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
21508c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        mLastTrack->meta->setInt32(kKeyEncoderPadding, padding);
21518c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    }
21525d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                }
21538c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
21545d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentMean.clear();
21555d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentName.clear();
21565d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentData.clear();
21575d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            }
21585d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            break;
21595d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        }
216026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
216172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        default:
216272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
216372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
216472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
216572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (size >= 8 && metadataKey) {
216672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        if (metadataKey == kKeyAlbumArt) {
216772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setData(
216872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    kKeyAlbumArt, MetaData::TYPE_NONE,
216972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    buffer + 8, size - 8);
217072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else if (metadataKey == kKeyGenre) {
217172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (flags == 0) {
217226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // uint8_t genre code, iTunes genre codes are
217326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // the standard id3 codes, except they start
217426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // at 1 instead of 0 (e.g. Pop is 14, not 13)
217526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // We use standard id3 numbering, so subtract 1.
217626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                int genrecode = (int)buffer[size - 1];
217726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                genrecode--;
217826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                if (genrecode < 0) {
217926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                    genrecode = 255; // reserved for 'unknown genre'
218026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                }
218172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char genre[10];
218226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                sprintf(genre, "%d", genrecode);
218372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
218472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(metadataKey, genre);
218526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            } else if (flags == 1) {
218626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // custom genre string
218726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                buffer[size] = '\0';
218826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
218926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(
219026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                        metadataKey, (const char *)buffer + 8);
219172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
219272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else {
219372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            buffer[size] = '\0';
219472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
219572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(
219672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    metadataKey, (const char *)buffer + 8);
219772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
219872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
219972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
220072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    delete[] buffer;
220172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    buffer = NULL;
220272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
220372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return OK;
220472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
220572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
2206693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
220720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
220820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
2209693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return NULL;
221020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
221120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
221220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
221320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
221420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
2215693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber            return NULL;
221620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
221720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
221820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
221920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
222020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
222120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2222371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
2223371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
2224371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
2225371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
2226ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("getTrack called, pssh: %d", mPssh.size());
2227ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2228693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    return new MPEG4Source(
222905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            track->meta, mDataSource, track->timescale, track->sampleTable,
223005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mSidxEntries, mMoofOffset);
223120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
223220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2233bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber// static
2234bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) {
2235bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const char *mime;
2236bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    CHECK(track->meta->findCString(kKeyMIMEType, &mime));
2237bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2238bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    uint32_t type;
2239bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const void *data;
2240bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    size_t size;
2241bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
2242bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyAVCC, &type, &data, &size)
2243bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeAVCC) {
2244bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
2245bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
2246bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
2247bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
2248bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyESDS, &type, &data, &size)
2249bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeESDS) {
2250bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
2251bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
2252bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    }
2253bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2254169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber    if (!track->sampleTable->isValid()) {
2255169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        // Make sure we have all the metadata we need.
2256169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        return ERROR_MALFORMED;
2257169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber    }
2258169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber
2259bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    return OK;
2260bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber}
2261bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2262ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
2263ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        const void *esds_data, size_t esds_size) {
2264ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    ESDS esds(esds_data, esds_size);
226581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
226681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    uint8_t objectTypeIndication;
226781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
226881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return ERROR_MALFORMED;
226981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
227081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
227181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (objectTypeIndication == 0xe1) {
227281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        // This isn't MPEG4 audio at all, it's QCELP 14k...
227381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
227481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return OK;
227581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
227681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
2277633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong    if (objectTypeIndication  == 0x6b) {
2278633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // The media subtype is MP3 audio
2279633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // Our software MP3 audio decoder may not be able to handle
2280633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // packetized MP3 audio; for now, lets just return ERROR_UNSUPPORTED
228129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("MP3 track in MP4/3GPP file is not supported");
2282633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        return ERROR_UNSUPPORTED;
2283633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong    }
2284633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong
2285ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    const uint8_t *csd;
2286ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    size_t csd_size;
2287ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (esds.getCodecSpecificInfo(
2288ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                (const void **)&csd, &csd_size) != OK) {
2289ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
2290ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2291ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2292ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#if 0
2293ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    printf("ESD of size %d\n", csd_size);
2294ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    hexdump(csd, csd_size);
2295ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#endif
2296ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2297a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    if (csd_size == 0) {
2298a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // There's no further information, i.e. no codec specific data
2299a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // Let's assume that the information provided in the mpeg4 headers
2300a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // is accurate and hope for the best.
2301a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
2302a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        return OK;
2303a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    }
2304a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
2305ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (csd_size < 2) {
2306ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
2307ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2308ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
23093c836e7882e88de42e0e600627de433b61e78621Eric Laurent    static uint32_t kSamplingRate[] = {
23103c836e7882e88de42e0e600627de433b61e78621Eric Laurent        96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
23113c836e7882e88de42e0e600627de433b61e78621Eric Laurent        16000, 12000, 11025, 8000, 7350
23123c836e7882e88de42e0e600627de433b61e78621Eric Laurent    };
23133c836e7882e88de42e0e600627de433b61e78621Eric Laurent
2314aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    ABitReader br(csd, csd_size);
2315aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    uint32_t objectType = br.getBits(5);
2316ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2317aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    if (objectType == 31) {  // AAC-ELD => additional 6 bits
2318aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        objectType = 32 + br.getBits(6);
2319ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2320ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2321f590f948e6c0fe3c54008dd7802fd513f127792dEric Laurent    //keep AOT type
2322f590f948e6c0fe3c54008dd7802fd513f127792dEric Laurent    mLastTrack->meta->setInt32(kKeyAACAOT, objectType);
2323f590f948e6c0fe3c54008dd7802fd513f127792dEric Laurent
2324aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    uint32_t freqIndex = br.getBits(4);
2325aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
2326ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t sampleRate = 0;
2327ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t numChannels = 0;
2328ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (freqIndex == 15) {
2329ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        if (csd_size < 5) {
2330ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            return ERROR_MALFORMED;
2331ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
2332aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        sampleRate = br.getBits(24);
2333aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        numChannels = br.getBits(4);
2334ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    } else {
2335595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen        numChannels = br.getBits(4);
23363c836e7882e88de42e0e600627de433b61e78621Eric Laurent
23373c836e7882e88de42e0e600627de433b61e78621Eric Laurent        if (freqIndex == 13 || freqIndex == 14) {
23383c836e7882e88de42e0e600627de433b61e78621Eric Laurent            return ERROR_MALFORMED;
2339ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
2340ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
23413c836e7882e88de42e0e600627de433b61e78621Eric Laurent        sampleRate = kSamplingRate[freqIndex];
23423c836e7882e88de42e0e600627de433b61e78621Eric Laurent    }
2343595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen
23443c836e7882e88de42e0e600627de433b61e78621Eric Laurent    if (objectType == 5 || objectType == 29) { // SBR specific config per 14496-3 table 1.13
23453c836e7882e88de42e0e600627de433b61e78621Eric Laurent        uint32_t extFreqIndex = br.getBits(4);
23463c836e7882e88de42e0e600627de433b61e78621Eric Laurent        int32_t extSampleRate;
23473c836e7882e88de42e0e600627de433b61e78621Eric Laurent        if (extFreqIndex == 15) {
23483c836e7882e88de42e0e600627de433b61e78621Eric Laurent            if (csd_size < 8) {
2349595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen                return ERROR_MALFORMED;
2350595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen            }
23513c836e7882e88de42e0e600627de433b61e78621Eric Laurent            extSampleRate = br.getBits(24);
23523c836e7882e88de42e0e600627de433b61e78621Eric Laurent        } else {
23533c836e7882e88de42e0e600627de433b61e78621Eric Laurent            if (extFreqIndex == 13 || extFreqIndex == 14) {
23543c836e7882e88de42e0e600627de433b61e78621Eric Laurent                return ERROR_MALFORMED;
23553c836e7882e88de42e0e600627de433b61e78621Eric Laurent            }
23563c836e7882e88de42e0e600627de433b61e78621Eric Laurent            extSampleRate = kSamplingRate[extFreqIndex];
2357595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen        }
23583c836e7882e88de42e0e600627de433b61e78621Eric Laurent        //TODO: save the extension sampling rate value in meta data =>
23593c836e7882e88de42e0e600627de433b61e78621Eric Laurent        //      mLastTrack->meta->setInt32(kKeyExtSampleRate, extSampleRate);
2360ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2361ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2362ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (numChannels == 0) {
2363ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_UNSUPPORTED;
2364ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2365ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2366ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevSampleRate;
2367ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
2368ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2369ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevSampleRate != sampleRate) {
23703856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("mpeg4 audio sample rate different from previous setting. "
2371ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevSampleRate, sampleRate);
2372ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2373ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2374ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
2375ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2376ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevChannelCount;
2377ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
2378ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2379ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevChannelCount != numChannels) {
23803856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("mpeg4 audio channel count different from previous setting. "
2381ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevChannelCount, numChannels);
2382ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2383ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2384ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
2385ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2386ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    return OK;
2387ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber}
2388ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
238920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
239020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
239120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::MPEG4Source(
239220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        const sp<MetaData> &format,
2393693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &dataSource,
239448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        int32_t timeScale,
239505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const sp<SampleTable> &sampleTable,
239605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        Vector<SidxEntry> &sidx,
239705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t firstMoofOffset)
239820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mFormat(format),
239920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDataSource(dataSource),
240048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber      mTimescale(timeScale),
240120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSampleTable(sampleTable),
240220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCurrentSampleIndex(0),
240305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentFragmentIndex(0),
240405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mSegments(sidx),
240505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mFirstMoofOffset(firstMoofOffset),
240605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentMoofOffset(firstMoofOffset),
240705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentTime(0),
2408ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoAllocSize(0),
2409ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoSizes(NULL),
2410ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoOffsetsAllocSize(0),
2411ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoOffsets(NULL),
241220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mIsAVC(false),
24136064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber      mNALLengthSize(0),
241420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mStarted(false),
241520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mGroup(NULL),
241620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mBuffer(NULL),
2417dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber      mWantsNALFragments(false),
24180024245e134467d120b40099da16c467dc365e76Andreas Huber      mSrcBuffer(NULL) {
2419ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2420ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mFormat->findInt32(kKeyCryptoMode, &mCryptoMode);
242148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    mDefaultIVSize = 0;
2422ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mFormat->findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize);
2423ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t keytype;
2424ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    const void *key;
2425ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    size_t keysize;
2426ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mFormat->findData(kKeyCryptoKey, &keytype, &key, &keysize)) {
2427ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        CHECK(keysize <= 16);
2428ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memset(mCryptoKey, 0, 16);
2429ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memcpy(mCryptoKey, key, keysize);
2430ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2431ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
243220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
243320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mFormat->findCString(kKeyMIMEType, &mime);
2434dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(success);
243520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
243618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber    mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
24376064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
24386064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    if (mIsAVC) {
24396064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        uint32_t type;
24406064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const void *data;
24416064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t size;
24426064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(format->findData(kKeyAVCC, &type, &data, &size));
24436064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
24446064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const uint8_t *ptr = (const uint8_t *)data;
24456064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
24466064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(size >= 7);
2447ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
24486064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
24496064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        // The number of bytes used to encode the length of a NAL unit.
24506064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        mNALLengthSize = 1 + (ptr[4] & 3);
24516064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
245205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
245305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    CHECK(format->findInt32(kKeyTrackID, &mTrackId));
245405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
245505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mFirstMoofOffset != 0) {
245605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t offset = mFirstMoofOffset;
245705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        parseChunk(&offset);
245805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
245920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
246020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
246120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::~MPEG4Source() {
246220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mStarted) {
246320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        stop();
246420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
2465ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    free(mCurrentSampleInfoSizes);
2466ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    free(mCurrentSampleInfoOffsets);
246720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
246820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
246920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::start(MetaData *params) {
24707b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
24717b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
2472dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(!mStarted);
247320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
247420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t val;
2475dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (params && params->findInt32(kKeyWantsNALFragments, &val)
247620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        && val != 0) {
2477dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = true;
247820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    } else {
2479dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = false;
248020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
248120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
248220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = new MediaBufferGroup;
248320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2484738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    int32_t max_size;
2485738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
248620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2487738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    mGroup->add_buffer(new MediaBuffer(max_size));
24880024245e134467d120b40099da16c467dc365e76Andreas Huber
24890024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = new uint8_t[max_size];
249020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
249120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = true;
249220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
249320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
249420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
249520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
249620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::stop() {
24977b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
24987b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
2499dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
250020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
250120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mBuffer != NULL) {
250220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->release();
250320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
250420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
250520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
25060024245e134467d120b40099da16c467dc365e76Andreas Huber    delete[] mSrcBuffer;
25070024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = NULL;
25080024245e134467d120b40099da16c467dc365e76Andreas Huber
250920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    delete mGroup;
251020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = NULL;
251120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
251220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = false;
251320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mCurrentSampleIndex = 0;
251420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
251520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
251620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
251720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
251805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseChunk(off64_t *offset) {
251905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t hdr[2];
252005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
252105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_IO;
252205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
252305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t chunk_size = ntohl(hdr[0]);
252405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t chunk_type = ntohl(hdr[1]);
252505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t data_offset = *offset + 8;
252605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
252705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (chunk_size == 1) {
252805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
252905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_IO;
253005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
253105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        chunk_size = ntoh64(chunk_size);
253205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        data_offset += 8;
253305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
253405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (chunk_size < 16) {
253505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            // The smallest valid chunk is 16 bytes long in this case.
253605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
253705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
253805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (chunk_size < 8) {
253905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // The smallest valid chunk is 8 bytes long.
254005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
254105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
254205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
254305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    char chunk[5];
254405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    MakeFourCCString(chunk_type, chunk);
254505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Source chunk %s @ %llx", chunk, *offset);
254605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
254705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t chunk_data_size = *offset + chunk_size - data_offset;
254805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
254905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    switch(chunk_type) {
255005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
255105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'r', 'a', 'f'):
255205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('m', 'o', 'o', 'f'): {
255305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t stop_offset = *offset + chunk_size;
255405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset = data_offset;
255505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            while (*offset < stop_offset) {
255605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err = parseChunk(offset);
255705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (err != OK) {
255805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return err;
255905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
256005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
256105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
2562ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // *offset points to the mdat box following this moof
256305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                parseChunk(offset); // doesn't actually parse it, just updates offset
256405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mNextMoofOffset = *offset;
256505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
256605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
256705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
256805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
256905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'f', 'h', 'd'): {
257005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err;
257105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if ((err = parseTrackFragmentHeader(data_offset, chunk_data_size)) != OK) {
257205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return err;
257305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
257405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                *offset += chunk_size;
257505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                break;
257605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
257705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
257805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'r', 'u', 'n'): {
257905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err;
258005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (mLastParsedTrackId == mTrackId) {
258105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    if ((err = parseTrackFragmentRun(data_offset, chunk_data_size)) != OK) {
258205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        return err;
258305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    }
258405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
258505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
258605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                *offset += chunk_size;
258705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                break;
258805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
258905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2590ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'a', 'i', 'z'): {
2591ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            status_t err;
2592ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((err = parseSampleAuxiliaryInformationSizes(data_offset, chunk_data_size)) != OK) {
2593ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return err;
2594ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
2595ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
2596ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
2597ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2598ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'a', 'i', 'o'): {
2599ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            status_t err;
2600ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((err = parseSampleAuxiliaryInformationOffsets(data_offset, chunk_data_size)) != OK) {
2601ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return err;
2602ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
2603ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
2604ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
2605ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2606ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2607ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('m', 'd', 'a', 't'): {
2608ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // parse DRM info if present
2609ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("MPEG4Source::parseChunk mdat");
2610ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // if saiz/saoi was previously observed, do something with the sampleinfos
2611ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
2612ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
2613ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2614ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
261505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        default: {
261605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset += chunk_size;
261705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
261805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
261905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
262005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
262105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
262205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2623ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissenstatus_t MPEG4Source::parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size) {
2624ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("parseSampleAuxiliaryInformationSizes");
2625ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // 14496-12 8.7.12
2626ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t version;
2627ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(
2628ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset, &version, sizeof(version))
2629ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            < (ssize_t)sizeof(version)) {
2630ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
2631ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2632ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2633ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (version != 0) {
2634ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_UNSUPPORTED;
2635ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2636ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
2637ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2638ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t flags;
2639ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt24(offset, &flags)) {
2640ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
2641ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2642ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 3;
2643ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2644ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (flags & 1) {
2645ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        uint32_t tmp;
2646ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
2647ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_MALFORMED;
2648ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2649ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentAuxInfoType = tmp;
2650ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        offset += 4;
2651ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
2652ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_MALFORMED;
2653ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2654ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentAuxInfoTypeParameter = tmp;
2655ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        offset += 4;
2656ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2657ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2658ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t defsize;
2659ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(offset, &defsize, 1) != 1) {
2660ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_MALFORMED;
2661ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2662ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mCurrentDefaultSampleInfoSize = defsize;
2663ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
2664ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2665ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t smplcnt;
2666ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &smplcnt)) {
2667ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_MALFORMED;
2668ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
266948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    mCurrentSampleInfoCount = smplcnt;
2670ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 4;
2671ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
267248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (mCurrentDefaultSampleInfoSize != 0) {
267348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        ALOGV("@@@@ using default sample info size of %d", mCurrentDefaultSampleInfoSize);
267448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return OK;
267548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
2676ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (smplcnt > mCurrentSampleInfoAllocSize) {
2677ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoSizes = (uint8_t*) realloc(mCurrentSampleInfoSizes, smplcnt);
2678ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoAllocSize = smplcnt;
2679ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2680ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2681ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mDataSource->readAt(offset, mCurrentSampleInfoSizes, smplcnt);
2682ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    return OK;
2683ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen}
2684ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2685ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissenstatus_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size) {
2686ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("parseSampleAuxiliaryInformationOffsets");
2687ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // 14496-12 8.7.13
2688ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t version;
2689ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(offset, &version, sizeof(version)) != 1) {
2690ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
2691ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2692ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
2693ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2694ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t flags;
2695ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt24(offset, &flags)) {
2696ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
2697ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2698ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 3;
2699ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2700ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t entrycount;
2701ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &entrycount)) {
2702ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
2703ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2704ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 4;
2705ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2706ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (entrycount > mCurrentSampleInfoOffsetsAllocSize) {
2707ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoOffsets = (uint64_t*) realloc(mCurrentSampleInfoOffsets, entrycount * 8);
2708ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoOffsetsAllocSize = entrycount;
2709ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2710ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mCurrentSampleInfoOffsetCount = entrycount;
2711ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2712ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < entrycount; i++) {
2713ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (version == 0) {
2714ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t tmp;
2715ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (!mDataSource->getUInt32(offset, &tmp)) {
2716ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
2717ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
2718ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mCurrentSampleInfoOffsets[i] = tmp;
2719ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset += 4;
2720ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        } else {
2721ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint64_t tmp;
2722ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (!mDataSource->getUInt64(offset, &tmp)) {
2723ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
2724ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
2725ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mCurrentSampleInfoOffsets[i] = tmp;
2726ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset += 8;
2727ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2728ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2729ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2730ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // parse clear/encrypted data
2731ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2732ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    off64_t drmoffset = mCurrentSampleInfoOffsets[0]; // from moof
2733ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2734ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    drmoffset += mCurrentMoofOffset;
2735ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int ivlength;
2736ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    CHECK(mFormat->findInt32(kKeyCryptoDefaultIVSize, &ivlength));
273748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
273848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    // read CencSampleAuxiliaryDataFormats
2739ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mCurrentSampleInfoCount; i++) {
2740ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Sample *smpl = &mCurrentSamples.editItemAt(i);
2741ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2742ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memset(smpl->iv, 0, 16);
2743ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (mDataSource->readAt(drmoffset, smpl->iv, ivlength) != ivlength) {
2744ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_IO;
2745ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2746ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2747ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        drmoffset += ivlength;
2748ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
274948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        int32_t smplinfosize = mCurrentDefaultSampleInfoSize;
275048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        if (smplinfosize == 0) {
275148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smplinfosize = mCurrentSampleInfoSizes[i];
2752ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
275348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        if (smplinfosize > ivlength) {
275448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint16_t numsubsamples;
275548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (!mDataSource->getUInt16(drmoffset, &numsubsamples)) {
2756ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
2757ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
2758ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            drmoffset += 2;
275948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            for (size_t j = 0; j < numsubsamples; j++) {
276048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                uint16_t numclear;
276148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                uint32_t numencrypted;
276248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                if (!mDataSource->getUInt16(drmoffset, &numclear)) {
276348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                    return ERROR_IO;
276448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                }
276548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                drmoffset += 2;
276648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                if (!mDataSource->getUInt32(drmoffset, &numencrypted)) {
276748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                    return ERROR_IO;
276848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                }
276948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                drmoffset += 4;
277048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->clearsizes.add(numclear);
277148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->encryptedsizes.add(numencrypted);
2772ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
277348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        } else {
277448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smpl->clearsizes.add(0);
277548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smpl->encryptedsizes.add(smpl->size);
2776ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2777ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2778ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2779ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2780ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    return OK;
2781ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen}
2782ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
278305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentHeader(off64_t offset, off64_t size) {
278405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
278505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 8) {
278605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
278705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
278805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
278905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
2790ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags
279105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
279205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
279305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
279405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & 0xff000000) {
279505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
279605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
279705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
279805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, (uint32_t*)&mLastParsedTrackId)) {
279905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
280005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
280105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
280205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mLastParsedTrackId != mTrackId) {
280305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // this is not the right track, skip it
280405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
280505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
280605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
280705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mFlags = flags;
280805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mTrackID = mLastParsedTrackId;
280905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 8;
281005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 8;
281105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
281205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("fragment header: %08x %08x", flags, mTrackFragmentHeaderInfo.mTrackID);
281305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
281405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent) {
281505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 8) {
281605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
281705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
281805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
281905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset, &mTrackFragmentHeaderInfo.mBaseDataOffset)) {
282005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
282105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
282205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 8;
282305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 8;
282405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
282505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
282605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent) {
282705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
282805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
282905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
283005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
283105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mSampleDescriptionIndex)) {
283205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
283305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
283405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
283505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
283605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
283705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
283805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
283905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
284005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
284105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
284205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
284305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleDuration)) {
284405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
284505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
284605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
284705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
284805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
284905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
285005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
285105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
285205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
285305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
285405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
285505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleSize)) {
285605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
285705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
285805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
285905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
286005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
286105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
286205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
286305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
286405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
286505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
286605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
286705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleFlags)) {
286805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
286905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
287005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
287105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
287205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
287305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
287405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!(flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent)) {
287505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mTrackFragmentHeaderInfo.mBaseDataOffset = mCurrentMoofOffset;
287605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
287705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
287805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mDataOffset = 0;
287905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
288005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
288105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
288205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentRun(off64_t offset, off64_t size) {
288305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
288405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Extractor::parseTrackFragmentRun");
288505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 8) {
288605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
288705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
288805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
288905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    enum {
289005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kDataOffsetPresent                  = 0x01,
289105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kFirstSampleFlagsPresent            = 0x04,
289205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleDurationPresent              = 0x100,
289305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleSizePresent                  = 0x200,
289405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleFlagsPresent                 = 0x400,
289505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleCompositionTimeOffsetPresent = 0x800,
289605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
289705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
289805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
289905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) {
290005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
290105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
290205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("fragment run flags: %08x", flags);
290305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
290405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & 0xff000000) {
290505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
290605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
290705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
290805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if ((flags & kFirstSampleFlagsPresent) && (flags & kSampleFlagsPresent)) {
290905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // These two shall not be used together.
291005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
291105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
291205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
291305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t sampleCount;
291405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, &sampleCount)) {
291505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
291605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
291705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 8;
291805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 8;
291905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
292005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t dataOffset = mTrackFragmentHeaderInfo.mDataOffset;
292105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
292205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t firstSampleFlags = 0;
292305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
292405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kDataOffsetPresent) {
292505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
292605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
292705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
292805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
292905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int32_t dataOffsetDelta;
293005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, (uint32_t*)&dataOffsetDelta)) {
293105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
293205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
293305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
293405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        dataOffset = mTrackFragmentHeaderInfo.mBaseDataOffset + dataOffsetDelta;
293505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
293605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
293705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
293805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
293905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
294005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kFirstSampleFlagsPresent) {
294105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
294205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
294305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
294405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
294505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &firstSampleFlags)) {
294605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
294705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
294805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
294905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
295005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
295105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
295205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t sampleDuration = 0, sampleSize = 0, sampleFlags = 0,
295305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen             sampleCtsOffset = 0;
295405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
295505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size_t bytesPerSample = 0;
295605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleDurationPresent) {
295705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
295805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
295905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
296005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration;
296105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
296205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration;
296305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
296405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
296505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleSizePresent) {
296605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
296705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
296805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
296905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
297005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
297105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
297205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
297305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
297405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleFlagsPresent) {
297505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
297605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
297705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
297805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
297905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
298005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
298105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
298205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
298305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleCompositionTimeOffsetPresent) {
298405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
298505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
298605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleCtsOffset = 0;
298705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
298805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
298905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < sampleCount * bytesPerSample) {
299005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
299105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
299205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
299305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Sample tmp;
299405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    for (uint32_t i = 0; i < sampleCount; ++i) {
299505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleDurationPresent) {
299605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleDuration)) {
299705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
299805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
299905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
300005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
300105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
300205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleSizePresent) {
300305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleSize)) {
300405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
300505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
300605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
300705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
300805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
300905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleFlagsPresent) {
301005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleFlags)) {
301105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
301205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
301305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
301405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
301505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
301605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleCompositionTimeOffsetPresent) {
301705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleCtsOffset)) {
301805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
301905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
302005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
302105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
302205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3023ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        ALOGV("adding sample %d at offset 0x%08llx, size %u, duration %u, "
3024ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen              " flags 0x%08x", i + 1,
302505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dataOffset, sampleSize, sampleDuration,
302605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                (flags & kFirstSampleFlagsPresent) && i == 0
302705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ? firstSampleFlags : sampleFlags);
302805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.offset = dataOffset;
302905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.size = sampleSize;
303005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.duration = sampleDuration;
303105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentSamples.add(tmp);
303205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
303305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        dataOffset += sampleSize;
303405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
303505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
303605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mDataOffset = dataOffset;
303705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
303805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
303905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
304005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
304120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> MPEG4Source::getFormat() {
30427b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
30437b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
304420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return mFormat;
304520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
304620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30476064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const {
30486064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    switch (mNALLengthSize) {
30496064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 1:
30506064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return *data;
30516064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 2:
30526064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U16_AT(data);
30536064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 3:
30546064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return ((size_t)data[0] << 16) | U16_AT(&data[1]);
30556064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 4:
30566064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U32_AT(data);
30576064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
30586064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
30596064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // This cannot happen, mNALLengthSize springs to life by adding 1 to
30606064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // a 2-bit integer.
30616064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    CHECK(!"Should not be here.");
30626064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
30636064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    return 0;
30646064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber}
30656064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
306620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::read(
306720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
30687b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
30697b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
3070dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
307120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
307205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mFirstMoofOffset > 0) {
307305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return fragmentedRead(out, options);
307405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
307505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
307620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *out = NULL;
307720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3078abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    int64_t targetSampleTimeUs = -1;
3079abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
308020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t seekTimeUs;
3081abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
3082abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
3083abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t findFlags = 0;
3084abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        switch (mode) {
3085abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_PREVIOUS_SYNC:
3086abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagBefore;
3087abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3088abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_NEXT_SYNC:
3089abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagAfter;
3090abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3091abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST_SYNC:
3092abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST:
3093abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagClosest;
3094abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3095abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            default:
3096abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                CHECK(!"Should not be here.");
3097abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3098abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3099abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
310020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        uint32_t sampleIndex;
3101abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        status_t err = mSampleTable->findSampleAtTime(
310220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                seekTimeUs * mTimescale / 1000000,
3103abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                &sampleIndex, findFlags);
3104abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3105abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
3106abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // We found the closest sample already, now we want the sync
3107abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // sample preceding it (or the sample itself of course), even
3108abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // if the subsequent sync sample is closer.
3109abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            findFlags = SampleTable::kFlagBefore;
3110abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3111abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3112abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleIndex;
3113abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (err == OK) {
3114abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            err = mSampleTable->findSyncSampleNear(
3115abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    sampleIndex, &syncSampleIndex, findFlags);
3116abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
311720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3118788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        uint32_t sampleTime;
3119788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        if (err == OK) {
3120788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber            err = mSampleTable->getMetaDataForSample(
3121788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber                    sampleIndex, NULL, NULL, &sampleTime);
3122788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        }
3123788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber
312420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (err != OK) {
31255295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            if (err == ERROR_OUT_OF_RANGE) {
31265295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // An attempt to seek past the end of the stream would
31275295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // normally cause this ERROR_OUT_OF_RANGE error. Propagating
31285295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // this all the way to the MediaPlayer would cause abnormal
31295295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // termination. Legacy behaviour appears to be to behave as if
31305295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // we had seeked to the end of stream, ending normally.
31315295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                err = ERROR_END_OF_STREAM;
31325295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            }
313305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("end of stream");
313420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return err;
313520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
313620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3137abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
3138abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
3139abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3140abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3141abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#if 0
3142abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleTime;
3143abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
3144abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    syncSampleIndex, NULL, NULL, &syncSampleTime));
3145abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3146df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("seek to time %lld us => sample at time %lld us, "
3147abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             "sync sample at time %lld us",
3148abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             seekTimeUs,
3149abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             sampleTime * 1000000ll / mTimescale,
3150abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             syncSampleTime * 1000000ll / mTimescale);
3151abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#endif
3152abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3153abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        mCurrentSampleIndex = syncSampleIndex;
315420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mBuffer != NULL) {
315520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
315620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
315720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
315820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
315920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // fall through
316020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
316120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3162c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset;
31630024245e134467d120b40099da16c467dc365e76Andreas Huber    size_t size;
31644678a6dc5f09008481524949a9667af5a6190374Andreas Huber    uint32_t cts;
31658bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    bool isSyncSample;
3166dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool newBuffer = false;
3167dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (mBuffer == NULL) {
3168dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        newBuffer = true;
316920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3170c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        status_t err =
3171c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber            mSampleTable->getMetaDataForSample(
31724678a6dc5f09008481524949a9667af5a6190374Andreas Huber                    mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample);
317320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3174dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
3175dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
3176dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3177dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3178dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        err = mGroup->acquire_buffer(&mBuffer);
3179c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
3180dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
3181ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            CHECK(mBuffer == NULL);
3182dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
3183dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
31840024245e134467d120b40099da16c467dc365e76Andreas Huber    }
318520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3186dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (!mIsAVC || mWantsNALFragments) {
3187dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (newBuffer) {
3188dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ssize_t num_bytes_read =
318934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
3190dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3191dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            if (num_bytes_read < (ssize_t)size) {
3192dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer->release();
3193dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer = NULL;
3194dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3195dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                return ERROR_IO;
3196dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            }
3197dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
31987b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber            CHECK(mBuffer != NULL);
3199dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->set_range(0, size);
3200dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->meta_data()->clear();
320148c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mBuffer->meta_data()->setInt64(
32024678a6dc5f09008481524949a9667af5a6190374Andreas Huber                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
3203abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3204abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            if (targetSampleTimeUs >= 0) {
3205abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                mBuffer->meta_data()->setInt64(
3206abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                        kKeyTargetTime, targetSampleTimeUs);
3207abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            }
3208abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
32098bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            if (isSyncSample) {
32108bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
32118bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            }
32128bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
3213dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ++mCurrentSampleIndex;
3214dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3215dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3216dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (!mIsAVC) {
3217dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            *out = mBuffer;
3218dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
3219dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3220dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return OK;
3221dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3222dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3223dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Each NAL unit is split up into its constituent fragments and
3224dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // each one of them returned in its own buffer.
3225dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
32266064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(mBuffer->range_length() >= mNALLengthSize);
3227dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3228dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        const uint8_t *src =
3229dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
3230dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
32316064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t nal_size = parseNALSize(src);
3232e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
323329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("incomplete NAL unit.");
3234e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3235e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer->release();
3236e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer = NULL;
3237e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3238e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            return ERROR_MALFORMED;
3239e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        }
3240dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3241dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        MediaBuffer *clone = mBuffer->clone();
32427b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(clone != NULL);
32436064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
3244dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
32457b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(mBuffer != NULL);
3246dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mBuffer->set_range(
32476064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_offset() + mNALLengthSize + nal_size,
32486064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_length() - mNALLengthSize - nal_size);
3249dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3250dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (mBuffer->range_length() == 0) {
3251dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->release();
3252dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
3253dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3254dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3255dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        *out = clone;
3256dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3257dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        return OK;
3258dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    } else {
3259dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Whole NAL units are returned but each fragment is prefixed by
3260dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // the start code (0x00 00 00 01).
3261dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        ssize_t num_bytes_read = 0;
3262dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        int32_t drm = 0;
3263dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
3264dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (usesDRM) {
3265dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            num_bytes_read =
3266dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
3267dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
3268dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
3269dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
327020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
327120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (num_bytes_read < (ssize_t)size) {
327220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
327320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
327420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3275dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return ERROR_IO;
327620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
327720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3278dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (usesDRM) {
3279dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK(mBuffer != NULL);
3280dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            mBuffer->set_range(0, size);
32816064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
3282dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
3283dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            uint8_t *dstData = (uint8_t *)mBuffer->data();
3284dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size_t srcOffset = 0;
3285dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size_t dstOffset = 0;
3286e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3287dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            while (srcOffset < size) {
328867a30ebfe785f7cd5ecfb0d2fb487e54536a3d48Lajos Molnar                bool isMalFormed = !isInRange(0u, size, srcOffset, mNALLengthSize);
328934fe252c89e33572d01fea981b58d7b115e76164James Dong                size_t nalLength = 0;
329034fe252c89e33572d01fea981b58d7b115e76164James Dong                if (!isMalFormed) {
329134fe252c89e33572d01fea981b58d7b115e76164James Dong                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
329234fe252c89e33572d01fea981b58d7b115e76164James Dong                    srcOffset += mNALLengthSize;
329367a30ebfe785f7cd5ecfb0d2fb487e54536a3d48Lajos Molnar                    isMalFormed = !isInRange(0u, size, srcOffset, nalLength);
329434fe252c89e33572d01fea981b58d7b115e76164James Dong                }
3295e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
329634fe252c89e33572d01fea981b58d7b115e76164James Dong                if (isMalFormed) {
329729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                    ALOGE("Video is malformed");
3298dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    mBuffer->release();
3299dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    mBuffer = NULL;
3300dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return ERROR_MALFORMED;
3301dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
3302dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
3303dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                if (nalLength == 0) {
3304dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    continue;
3305dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
3306dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3307dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                CHECK(dstOffset + 4 <= mBuffer->size());
3308dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3309dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3310dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3311dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3312dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 1;
3313dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
3314dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                srcOffset += nalLength;
3315dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstOffset += nalLength;
3316dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
3317dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK_EQ(srcOffset, size);
3318dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK(mBuffer != NULL);
3319dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            mBuffer->set_range(0, dstOffset);
3320dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3321dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
332220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->meta_data()->clear();
332348c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        mBuffer->meta_data()->setInt64(
33244678a6dc5f09008481524949a9667af5a6190374Andreas Huber                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
3325abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3326abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (targetSampleTimeUs >= 0) {
3327abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            mBuffer->meta_data()->setInt64(
3328abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    kKeyTargetTime, targetSampleTimeUs);
3329abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3330abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
33318bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        if (isSyncSample) {
33328bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
33338bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        }
33348bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
333520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        ++mCurrentSampleIndex;
333620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
333720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        *out = mBuffer;
333820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
333920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
334020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
334120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
334220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
334320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
334405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::fragmentedRead(
334505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MediaBuffer **out, const ReadOptions *options) {
334605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
334705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Source::fragmentedRead");
334805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
334905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    CHECK(mStarted);
335005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
335105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    *out = NULL;
335205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
335305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t targetSampleTimeUs = -1;
335405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
335505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t seekTimeUs;
335605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ReadOptions::SeekMode mode;
335705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
335805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
335905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int numSidxEntries = mSegments.size();
336005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (numSidxEntries != 0) {
336105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            int64_t totalTime = 0;
336205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t totalOffset = mFirstMoofOffset;
336305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            for (int i = 0; i < numSidxEntries; i++) {
336405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                const SidxEntry *se = &mSegments[i];
336505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (totalTime + se->mDurationUs > seekTimeUs) {
336605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    // The requested time is somewhere in this segment
336705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    if ((mode == ReadOptions::SEEK_NEXT_SYNC) ||
336805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        (mode == ReadOptions::SEEK_CLOSEST_SYNC &&
336905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        (seekTimeUs - totalTime) > (totalTime + se->mDurationUs - seekTimeUs))) {
337005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        // requested next sync, or closest sync and it was closer to the end of
337105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        // this segment
337205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        totalTime += se->mDurationUs;
337305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        totalOffset += se->mSize;
337405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    }
337505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    break;
337605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
337705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                totalTime += se->mDurationUs;
337805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                totalOffset += se->mSize;
337905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
338005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentMoofOffset = totalOffset;
338105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentSamples.clear();
338205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentSampleIndex = 0;
338305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        parseChunk(&totalOffset);
338405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentTime = totalTime * mTimescale / 1000000ll;
338505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
338605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
338705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer != NULL) {
338805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
338905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
339005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
339105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
339205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // fall through
339305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
339405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
339505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t offset = 0;
339605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size_t size;
339705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t cts = 0;
339805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    bool isSyncSample = false;
339905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    bool newBuffer = false;
340005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mBuffer == NULL) {
340105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        newBuffer = true;
340205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
340305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mCurrentSampleIndex >= mCurrentSamples.size()) {
340405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            // move to next fragment
340505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            Sample lastSample = mCurrentSamples[mCurrentSamples.size() - 1];
340605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t nextMoof = mNextMoofOffset; // lastSample.offset + lastSample.size;
340705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentMoofOffset = nextMoof;
340805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentSamples.clear();
340905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentSampleIndex = 0;
341005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            parseChunk(&nextMoof);
341105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (mCurrentSampleIndex >= mCurrentSamples.size()) {
341205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return ERROR_END_OF_STREAM;
341305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
341405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
341505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
341605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
341705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset = smpl->offset;
341805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size = smpl->size;
341905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        cts = mCurrentTime;
342005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentTime += smpl->duration;
342105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        isSyncSample = (mCurrentSampleIndex == 0); // XXX
342205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
342305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        status_t err = mGroup->acquire_buffer(&mBuffer);
342405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
342505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (err != OK) {
342605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer == NULL);
342705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("acquire_buffer returned %d", err);
342805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return err;
342905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
343005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
343105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
343248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
343348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    const sp<MetaData> bufmeta = mBuffer->meta_data();
343448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    bufmeta->clear();
343548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (smpl->encryptedsizes.size()) {
343648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // store clear/encrypted lengths in metadata
343748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyPlainSizes, 0,
343848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->clearsizes.array(), smpl->clearsizes.size() * 4);
343948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyEncryptedSizes, 0,
344048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
344148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
344248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
344348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setInt32(kKeyCryptoMode, mCryptoMode);
344448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16);
344548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
344648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
344705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mIsAVC || mWantsNALFragments) {
344805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (newBuffer) {
3449f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            if (!isInRange((size_t)0u, mBuffer->size(), size)) {
3450f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                mBuffer->release();
3451f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                mBuffer = NULL;
3452f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih
3453f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                ALOGE("fragmentedRead ERROR_MALFORMED size %zu", size);
3454f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                return ERROR_MALFORMED;
3455f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            }
3456f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih
345705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ssize_t num_bytes_read =
345805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
345905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
346005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (num_bytes_read < (ssize_t)size) {
346105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->release();
346205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer = NULL;
346305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3464f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                ALOGE("i/o error");
346505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_IO;
346605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
346705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
346805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
346905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, size);
347005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt64(
347105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
347205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
347305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (targetSampleTimeUs >= 0) {
347405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->meta_data()->setInt64(
347505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        kKeyTargetTime, targetSampleTimeUs);
347605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
347705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
347805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (isSyncSample) {
347905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
348005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
348105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
348205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ++mCurrentSampleIndex;
348305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
348405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
348505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mIsAVC) {
348605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *out = mBuffer;
348705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
348805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
348905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return OK;
349005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
349105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
349205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // Each NAL unit is split up into its constituent fragments and
349305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // each one of them returned in its own buffer.
349405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
349505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(mBuffer->range_length() >= mNALLengthSize);
349605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
349705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const uint8_t *src =
349805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
349905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
350005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size_t nal_size = parseNALSize(src);
350105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
350205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGE("incomplete NAL unit.");
350305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
350405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
350505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
350605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
350705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
350805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
350905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
351005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MediaBuffer *clone = mBuffer->clone();
351105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(clone != NULL);
351205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
351305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
351405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(mBuffer != NULL);
351505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer->set_range(
351605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->range_offset() + mNALLengthSize + nal_size,
351705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->range_length() - mNALLengthSize - nal_size);
351805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
351905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer->range_length() == 0) {
352005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
352105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
352205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
352305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
352405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        *out = clone;
352505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
352605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
352705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
352805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV("whole NAL");
352905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // Whole NAL units are returned but each fragment is prefixed by
353005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // the start code (0x00 00 00 01).
353105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ssize_t num_bytes_read = 0;
353205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int32_t drm = 0;
353305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
3534f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih        void *data = NULL;
3535f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih        bool isMalFormed = false;
353605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (usesDRM) {
3537f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            if (mBuffer == NULL || !isInRange((size_t)0u, mBuffer->size(), size)) {
3538f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                isMalFormed = true;
3539f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            } else {
3540f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                data = mBuffer->data();
3541f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            }
354205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else {
3543f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            int32_t max_size;
3544f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            if (mFormat == NULL
3545f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                    || !mFormat->findInt32(kKeyMaxInputSize, &max_size)
3546f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                    || !isInRange((size_t)0u, (size_t)max_size, size)) {
3547f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                isMalFormed = true;
3548f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            } else {
3549f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                data = mSrcBuffer;
3550f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            }
355105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
355205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3553f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih        if (isMalFormed || data == NULL) {
3554f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            ALOGE("isMalFormed size %zu", size);
3555f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            if (mBuffer != NULL) {
3556f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                mBuffer->release();
3557f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                mBuffer = NULL;
3558f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            }
3559f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            return ERROR_MALFORMED;
3560f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih        }
3561f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih        num_bytes_read = mDataSource->readAt(offset, data, size);
3562f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih
356305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (num_bytes_read < (ssize_t)size) {
356405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
356505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
356605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3567f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            ALOGE("i/o error");
356805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_IO;
356905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
357005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
357105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (usesDRM) {
357205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
357305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, size);
357405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
357505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else {
357605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            uint8_t *dstData = (uint8_t *)mBuffer->data();
357705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            size_t srcOffset = 0;
357805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            size_t dstOffset = 0;
357905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
358005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            while (srcOffset < size) {
3581f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                isMalFormed = !isInRange((size_t)0u, size, srcOffset, mNALLengthSize);
358205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                size_t nalLength = 0;
358305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (!isMalFormed) {
358405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
358505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    srcOffset += mNALLengthSize;
3586f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                    isMalFormed = !isInRange((size_t)0u, size, srcOffset, nalLength)
3587f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                            || !isInRange((size_t)0u, mBuffer->size(), dstOffset, (size_t)4u)
3588f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                            || !isInRange((size_t)0u, mBuffer->size(), dstOffset + 4, nalLength);
358905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
359005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
359105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (isMalFormed) {
3592f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                    ALOGE("Video is malformed; nalLength %zu", nalLength);
359305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    mBuffer->release();
359405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    mBuffer = NULL;
359505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return ERROR_MALFORMED;
359605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
359705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
359805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (nalLength == 0) {
359905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    continue;
360005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
360105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
360205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                CHECK(dstOffset + 4 <= mBuffer->size());
360305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
360405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
360505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
360605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
360705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 1;
360805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
360905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                srcOffset += nalLength;
361005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstOffset += nalLength;
361105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
361205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK_EQ(srcOffset, size);
361305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
361405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, dstOffset);
361505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
361605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
361705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer->meta_data()->setInt64(
361805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
361905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
362005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (targetSampleTimeUs >= 0) {
362105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt64(
362205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    kKeyTargetTime, targetSampleTimeUs);
362305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
362405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
362505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (isSyncSample) {
362605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
362705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
362805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
362905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ++mCurrentSampleIndex;
363005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
363105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        *out = mBuffer;
363205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer = NULL;
363305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
363405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
363505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
363605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
363705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3638bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas HuberMPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix(
3639bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        const char *mimePrefix) {
3640bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    for (Track *track = mFirstTrack; track != NULL; track = track->next) {
3641bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        const char *mime;
3642bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        if (track->meta != NULL
3643bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                && track->meta->findCString(kKeyMIMEType, &mime)
3644bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) {
3645bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber            return track;
3646bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        }
3647bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    }
3648bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber
3649bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    return NULL;
3650bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber}
3651bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber
36521b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool LegacySniffMPEG4(
3653693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
365420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[8];
365520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
365634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    ssize_t n = source->readAt(4, header, sizeof(header));
365720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (n < (ssize_t)sizeof(header)) {
365820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return false;
365920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
366020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
366120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
3662b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8)
3663b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8)
36640dba73763a04d39faf999dcc5ef12af3c99535a7Andreas Huber        || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
3665ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
3666983b449a27b5fa91eca82ede5204b4341899be62Andreas Huber        || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
366718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
36685a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        *confidence = 0.4;
366920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
367020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return true;
367120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
367220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
367320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return false;
367420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
367520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36761b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool isCompatibleBrand(uint32_t fourcc) {
36771b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    static const uint32_t kCompatibleBrands[] = {
36781b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', 'm'),
36791b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', '2'),
36801b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('a', 'v', 'c', '1'),
36811b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('3', 'g', 'p', '4'),
36821b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '1'),
36831b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '2'),
36844cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong
36854cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        // Won't promise that the following file types can be played.
36864cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        // Just give these file types a chance.
36874cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        FOURCC('q', 't', ' ', ' '),  // Apple's QuickTime
36884cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        FOURCC('M', 'S', 'N', 'V'),  // Sony's PSP
368958fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber
369058fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber        FOURCC('3', 'g', '2', 'a'),  // 3GPP2
369158fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber        FOURCC('3', 'g', '2', 'b'),
36921b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    };
36931b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
36941b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    for (size_t i = 0;
36951b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]);
36961b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         ++i) {
36971b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        if (kCompatibleBrands[i] == fourcc) {
36981b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            return true;
36991b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
37001b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
37011b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
37021b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
37031b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
37041b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
37051b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// Attempt to actually parse the 'ftyp' atom and determine if a suitable
37061b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// compatible brand is present.
3707a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// Also try to identify where this file's metadata ends
3708a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// (end of the 'moov' atom) and report it to the caller as part of
3709a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// the metadata.
37101b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool BetterSniffMPEG4(
3711a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
3712a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        sp<AMessage> *meta) {
3713a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    // We scan up to 128 bytes to identify this file as an MP4.
3714a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    static const off64_t kMaxScanOffset = 128ll;
37151b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
3716a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    off64_t offset = 0ll;
3717a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    bool foundGoodFileType = false;
3718a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    off64_t moovAtomEndOffset = -1ll;
3719a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    bool done = false;
37201b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
3721a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    while (!done && offset < kMaxScanOffset) {
3722a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint32_t hdr[2];
3723a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        if (source->readAt(offset, hdr, 8) < 8) {
3724a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            return false;
3725a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        }
3726a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3727a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint64_t chunkSize = ntohl(hdr[0]);
3728a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint32_t chunkType = ntohl(hdr[1]);
3729a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        off64_t chunkDataOffset = offset + 8;
3730a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3731a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        if (chunkSize == 1) {
3732a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            if (source->readAt(offset + 8, &chunkSize, 8) < 8) {
37331b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                return false;
37341b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
37351b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
3736a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            chunkSize = ntoh64(chunkSize);
3737a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            chunkDataOffset += 8;
3738a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3739a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            if (chunkSize < 16) {
3740a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                // The smallest valid chunk is 16 bytes long in this case.
3741a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                return false;
3742a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            }
3743a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        } else if (chunkSize < 8) {
3744a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            // The smallest valid chunk is 8 bytes long.
3745a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            return false;
3746a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        }
3747a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3748a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        off64_t chunkDataSize = offset + chunkSize - chunkDataOffset;
3749a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
375005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        char chunkstring[5];
375105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MakeFourCCString(chunkType, chunkstring);
375205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV("saw chunk type %s, size %lld @ %lld", chunkstring, chunkSize, offset);
3753a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        switch (chunkType) {
3754a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            case FOURCC('f', 't', 'y', 'p'):
3755a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            {
3756a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                if (chunkDataSize < 8) {
3757a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    return false;
3758a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
3759a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3760a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4;
3761a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
3762a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (i == 1) {
3763a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        // Skip this index, it refers to the minorVersion,
3764a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        // not a brand.
3765a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        continue;
3766a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
3767a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3768a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    uint32_t brand;
3769a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (source->readAt(
3770a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                                chunkDataOffset + 4 * i, &brand, 4) < 4) {
3771a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        return false;
3772a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
3773a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3774a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    brand = ntohl(brand);
3775a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3776a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (isCompatibleBrand(brand)) {
3777a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        foundGoodFileType = true;
3778a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        break;
3779a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
3780a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
3781a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3782a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                if (!foundGoodFileType) {
3783a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    return false;
3784a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
3785a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
37861b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                break;
37871b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
3788a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3789a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            case FOURCC('m', 'o', 'o', 'v'):
3790a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            {
3791a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                moovAtomEndOffset = offset + chunkSize;
3792a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3793a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                done = true;
3794a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                break;
3795a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            }
3796a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3797a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            default:
3798a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                break;
37991b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
3800a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3801a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        offset += chunkSize;
38021b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
38031b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
3804a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (!foundGoodFileType) {
38051b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return false;
38061b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
38071b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
38081b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
38095a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber    *confidence = 0.4f;
38101b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
3811a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (moovAtomEndOffset >= 0) {
3812a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        *meta = new AMessage;
3813a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        (*meta)->setInt64("meta-data-size", moovAtomEndOffset);
3814a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3815456caf3f5f0af673dc120c17c23635f40d8f5ac2Andreas Huber        ALOGV("found metadata size: %lld", moovAtomEndOffset);
3816a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    }
3817a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
38181b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return true;
38191b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
38201b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
38211b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberbool SniffMPEG4(
38225a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
3823a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        sp<AMessage> *meta) {
3824a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (BetterSniffMPEG4(source, mimeType, confidence, meta)) {
38251b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
38261b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
38271b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
38281b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    if (LegacySniffMPEG4(source, mimeType, confidence)) {
38295ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Identified supported mpeg4 through LegacySniffMPEG4.");
38301b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
38311b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
38321b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
38331b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
38341b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
38351b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
383620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
3837