MPEG4Extractor.cpp revision 7e9ac3509d72e8dc6f1316b5ce0a0066638b9737
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.
1382e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                if (max_size > SIZE_MAX - 10 * 2) {
1383e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                    ALOGE("max sample size too big: %zu", max_size);
1384e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                    return ERROR_MALFORMED;
1385e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                }
138605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
138705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            } else {
138805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // No size was specified. Pick a conservatively large size.
1389e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                uint32_t width, height;
1390e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                if (!mLastTrack->meta->findInt32(kKeyWidth, (int32_t*)&width) ||
1391e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                    !mLastTrack->meta->findInt32(kKeyHeight,(int32_t*) &height)) {
139205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ALOGE("No width or height, assuming worst case 1080p");
1393f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    width = 1920;
1394f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    height = 1080;
1395e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                } else {
1396e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                    // A resolution was specified, check that it's not too big. The values below
1397e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                    // were chosen so that the calculations below don't cause overflows, they're
1398e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                    // not indicating that resolutions up to 32kx32k are actually supported.
1399e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                    if (width > 32768 || height > 32768) {
1400e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                        ALOGE("can't support %u x %u video", width, height);
1401e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                        return ERROR_MALFORMED;
1402e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                    }
140305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
1404f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar
14054256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen                const char *mime;
14064256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1407f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
1408f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // AVC requires compression ratio of at least 2, and uses
1409f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // macroblocks
1410f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    max_size = ((width + 15) / 16) * ((height + 15) / 16) * 192;
1411f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                } else {
1412f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // For all other formats there is no minimum compression
1413f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // ratio. Use compression ratio of 1.
1414f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    max_size = width * height * 3 / 2;
1415f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                }
1416f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size);
141705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
141820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
1419113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong
14204256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            // NOTE: setting another piece of metadata invalidates any pointers (such as the
14214256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            // mimetype) previously obtained, so don't cache them.
14224256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            const char *mime;
14234256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1424113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            // Calculate average frame rate.
1425113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            if (!strncasecmp("video/", mime, 6)) {
1426113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                size_t nSamples = mLastTrack->sampleTable->countSamples();
1427113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                int64_t durationUs;
1428113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                if (mLastTrack->meta->findInt64(kKeyDuration, &durationUs)) {
1429113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                    if (durationUs > 0) {
1430113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                        int32_t frameRate = (nSamples * 1000000LL +
1431113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                                    (durationUs >> 1)) / durationUs;
1432113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                        mLastTrack->meta->setInt32(kKeyFrameRate, frameRate);
1433113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                    }
1434113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                }
1435113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            }
1436113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong
143720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
143820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
143920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
144020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 't', 's'):
144120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
144220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
144320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setTimeToSampleParams(
144420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
144520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
144620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
144720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
144820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
144920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
145020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
145120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
145220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
145320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14544931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        case FOURCC('c', 't', 't', 's'):
14554931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        {
14564931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            status_t err =
14574931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                mLastTrack->sampleTable->setCompositionTimeToSampleParams(
14584931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                        data_offset, chunk_data_size);
14594931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
14604931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            if (err != OK) {
14614931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                return err;
14624931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            }
14634931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
14644931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            *offset += chunk_size;
14654931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            break;
14664931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        }
14674931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
146820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 's'):
146920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
147020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
147120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSyncSampleParams(
147220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
147320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
147420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
147520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
147620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
147720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
147820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
147920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
148020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
148120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14824948818cb91176df74c972ac27b2f392b5d148bcJames Dong        // @xyz
14834948818cb91176df74c972ac27b2f392b5d148bcJames Dong        case FOURCC('\xA9', 'x', 'y', 'z'):
14844948818cb91176df74c972ac27b2f392b5d148bcJames Dong        {
14854948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Best case the total data length inside "@xyz" box
14864948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // would be 8, for instance "@xyz" + "\x00\x04\x15\xc7" + "0+0/",
14874948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // where "\x00\x04" is the text string length with value = 4,
14884948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // "\0x15\xc7" is the language code = en, and "0+0" is a
14894948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // location (string) value with longitude = 0 and latitude = 0.
14904948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (chunk_data_size < 8) {
14914948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_MALFORMED;
14924948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
14934948818cb91176df74c972ac27b2f392b5d148bcJames Dong
14944948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Worst case the location string length would be 18,
14954948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // for instance +90.0000-180.0000, without the trailing "/" and
14964948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // the string length + language code.
14974948818cb91176df74c972ac27b2f392b5d148bcJames Dong            char buffer[18];
14984948818cb91176df74c972ac27b2f392b5d148bcJames Dong
14994948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Substracting 5 from the data size is because the text string length +
15004948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // language code takes 4 bytes, and the trailing slash "/" takes 1 byte.
15014948818cb91176df74c972ac27b2f392b5d148bcJames Dong            off64_t location_length = chunk_data_size - 5;
15024948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (location_length >= (off64_t) sizeof(buffer)) {
15034948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_MALFORMED;
15044948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
15054948818cb91176df74c972ac27b2f392b5d148bcJames Dong
15064948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (mDataSource->readAt(
15074948818cb91176df74c972ac27b2f392b5d148bcJames Dong                        data_offset + 4, buffer, location_length) < location_length) {
15084948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_IO;
15094948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
15104948818cb91176df74c972ac27b2f392b5d148bcJames Dong
15114948818cb91176df74c972ac27b2f392b5d148bcJames Dong            buffer[location_length] = '\0';
15124948818cb91176df74c972ac27b2f392b5d148bcJames Dong            mFileMetaData->setCString(kKeyLocation, buffer);
15134948818cb91176df74c972ac27b2f392b5d148bcJames Dong            *offset += chunk_size;
15144948818cb91176df74c972ac27b2f392b5d148bcJames Dong            break;
15154948818cb91176df74c972ac27b2f392b5d148bcJames Dong        }
15164948818cb91176df74c972ac27b2f392b5d148bcJames Dong
151720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('e', 's', 'd', 's'):
151820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
151920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
152020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
152120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
152220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
152320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[256];
1524c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size > (off64_t)sizeof(buffer)) {
152520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
152620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
152720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
152834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
152920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
153020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
153120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
153220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
153320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
153420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
153520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
153620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
153720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
153820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
153920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
154020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1541ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            if (mPath.size() >= 2
1542ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
1543ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // Information from the ESDS must be relied on for proper
1544ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // setup of sample rate and channel count for MPEG4 Audio.
1545ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // The generic header appears to only contain generic
1546ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // information...
1547ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1548ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio(
1549ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                        &buffer[4], chunk_data_size - 4);
1550ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1551ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                if (err != OK) {
1552ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    return err;
1553ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                }
1554ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            }
1555ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
155620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
155720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
155820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
155920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
156020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', 'C'):
156120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1562d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson            sp<ABuffer> buffer = new ABuffer(chunk_data_size);
156320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
156434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
1565d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson                        data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
156620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
156720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
156820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
156920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
1570d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson                    kKeyAVCC, kTypeAVCC, buffer->data(), chunk_data_size);
157120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
157220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
157320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
157420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
157520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1576244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        case FOURCC('d', '2', '6', '3'):
1577244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        {
157817e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            /*
157917e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * d263 contains a fixed 7 bytes part:
158017e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   vendor - 4 bytes
158117e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   version - 1 byte
158217e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   level - 1 byte
158317e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   profile - 1 byte
158417e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * optionally, "d263" box itself may contain a 16-byte
158517e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * bit rate box (bitr)
158617e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   average bit rate - 4 bytes
158717e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   max bit rate - 4 bytes
158817e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             */
158917e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            char buffer[23];
159017e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            if (chunk_data_size != 7 &&
159117e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong                chunk_data_size != 23) {
159229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Incorrect D263 box size %lld", chunk_data_size);
1593244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                return ERROR_MALFORMED;
1594244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            }
1595244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1596244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            if (mDataSource->readAt(
1597244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                    data_offset, buffer, chunk_data_size) < chunk_data_size) {
1598244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                return ERROR_IO;
1599244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            }
1600244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1601244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size);
1602244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1603244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            *offset += chunk_size;
1604244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            break;
1605244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        }
1606244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
160772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'e', 't', 'a'):
160872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
160972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            uint8_t buffer[4];
1610c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size < (off64_t)sizeof(buffer)) {
1611bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1612bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
1613bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
161472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
161572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, buffer, 4) < 4) {
161672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
161772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
161872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
161972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (U32_AT(buffer) != 0) {
162072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                // Should be version 0, flags 0.
1621ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
1622ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // If it's not, let's assume this is one of those
1623ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // apparently malformed chunks that don't have flags
1624ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // and completely different semantics than what's
1625ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // in the MPEG4 specs and skip it.
1626ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                *offset += chunk_size;
1627ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                return OK;
162872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
162972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1630c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
163172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset = data_offset + sizeof(buffer);
163272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            while (*offset < stop_offset) {
163372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                status_t err = parseChunk(offset, depth + 1);
163472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
163572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
163672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
163772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
1638bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1639bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1640bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1641bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
164272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
164372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
164472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
16455d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('m', 'e', 'a', 'n'):
16465d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('n', 'a', 'm', 'e'):
164772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('d', 'a', 't', 'a'):
164872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
164972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mPath.size() == 6 && underMetaDataPath(mPath)) {
165072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                status_t err = parseMetaData(data_offset, chunk_data_size);
165172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
165272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
165372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
165472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
165572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
165672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
165772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset += chunk_size;
165872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
165972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
166072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
166172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'v', 'h', 'd'):
166272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
1663fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            if (chunk_data_size < 24) {
166472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_MALFORMED;
166572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
166672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1667fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            uint8_t header[24];
166872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
166972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, header, sizeof(header))
167072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    < (ssize_t)sizeof(header)) {
167172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
167272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
167372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1674fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            uint64_t creationTime;
167572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (header[0] == 1) {
167672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U64_AT(&header[4]);
1677fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                mHeaderTimescale = U32_AT(&header[20]);
1678bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (header[0] != 0) {
1679bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
168072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            } else {
168172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U32_AT(&header[4]);
1682fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                mHeaderTimescale = U32_AT(&header[12]);
168372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
168472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
168572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            String8 s;
168672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            convertTimeToDate(creationTime, &s);
168772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
168872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(kKeyDate, s.string());
168972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
169072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset += chunk_size;
169172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
169272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
169372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1694dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        case FOURCC('m', 'd', 'a', 't'):
1695dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        {
1696ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("mdat chunk, drm: %d", mIsDrm);
1697dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (!mIsDrm) {
1698dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                *offset += chunk_size;
1699dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                break;
1700dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
1701dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
1702dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (chunk_size < 8) {
1703dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
1704dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
1705dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
1706dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return parseDrmSINF(offset, data_offset);
1707dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
1708dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
17093b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        case FOURCC('h', 'd', 'l', 'r'):
17103b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        {
17113b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t buffer;
17123b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (mDataSource->readAt(
17133b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                        data_offset + 8, &buffer, 4) < 4) {
17143b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_IO;
17153b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17163b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17173b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type = ntohl(buffer);
17183b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            // For the 3GPP file format, the handler-type within the 'hdlr' box
1719e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            // shall be 'text'. We also want to support 'sbtl' handler type
1720e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            // for a practical reason as various MPEG4 containers use it.
1721e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            if (type == FOURCC('t', 'e', 'x', 't') || type == FOURCC('s', 'b', 't', 'l')) {
17223b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
17233b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17243b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17253b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            *offset += chunk_size;
17263b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            break;
17273b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        }
17283b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17297a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        case FOURCC('t', 'x', '3', 'g'):
17307a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        {
17313b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type;
17323b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            const void *data;
17333b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            size_t size = 0;
17343b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (!mLastTrack->meta->findData(
17353b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    kKeyTextFormatData, &type, &data, &size)) {
17363b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                size = 0;
17373b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17383b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17390e20b2093aa2bbc93afed8d68d3765d18a431b74Nick Kralevich            if ((chunk_size > SIZE_MAX) || (SIZE_MAX - chunk_size <= size)) {
1740e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake                return ERROR_MALFORMED;
1741e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake            }
1742e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake
17433b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint8_t *buffer = new uint8_t[size + chunk_size];
1744e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake            if (buffer == NULL) {
1745e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake                return ERROR_MALFORMED;
1746e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake            }
17473b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17483b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (size > 0) {
17493b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                memcpy(buffer, data, size);
17503b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17513b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17523b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size))
17533b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    < chunk_size) {
17543b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                delete[] buffer;
17553b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                buffer = NULL;
17563b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17573b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_IO;
17583b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17593b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17603b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            mLastTrack->meta->setData(
17613b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    kKeyTextFormatData, 0, buffer, size + chunk_size);
17623b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17633b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            delete[] buffer;
17647a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
17657a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            *offset += chunk_size;
17667a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            break;
17677a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        }
17687a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
1769515e855eae78aa495da58356486aaa666cb57fd1James Dong        case FOURCC('c', 'o', 'v', 'r'):
1770515e855eae78aa495da58356486aaa666cb57fd1James Dong        {
1771515e855eae78aa495da58356486aaa666cb57fd1James Dong            if (mFileMetaData != NULL) {
17723856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("chunk_data_size = %lld and data_offset = %lld",
1773515e855eae78aa495da58356486aaa666cb57fd1James Dong                        chunk_data_size, data_offset);
177405ddc499b9d50c90f552ed1333110f28a1406e7cJoshua J. Drake
17757e9ac3509d72e8dc6f1316b5ce0a0066638b9737Dan Albert                if (chunk_data_size < 0 || static_cast<uint64_t>(chunk_data_size) >= SIZE_MAX - 1) {
177605ddc499b9d50c90f552ed1333110f28a1406e7cJoshua J. Drake                    return ERROR_MALFORMED;
177705ddc499b9d50c90f552ed1333110f28a1406e7cJoshua J. Drake                }
17781552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1);
1779515e855eae78aa495da58356486aaa666cb57fd1James Dong                if (mDataSource->readAt(
17801552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                    data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) {
1781515e855eae78aa495da58356486aaa666cb57fd1James Dong                    return ERROR_IO;
1782515e855eae78aa495da58356486aaa666cb57fd1James Dong                }
1783515e855eae78aa495da58356486aaa666cb57fd1James Dong                const int kSkipBytesOfDataBox = 16;
17844a492bf2ac47b9844d2527e1fcdf0064c3d8d52eJoshua J. Drake                if (chunk_data_size <= kSkipBytesOfDataBox) {
17854a492bf2ac47b9844d2527e1fcdf0064c3d8d52eJoshua J. Drake                    return ERROR_MALFORMED;
17864a492bf2ac47b9844d2527e1fcdf0064c3d8d52eJoshua J. Drake                }
17874a492bf2ac47b9844d2527e1fcdf0064c3d8d52eJoshua J. Drake
1788515e855eae78aa495da58356486aaa666cb57fd1James Dong                mFileMetaData->setData(
1789515e855eae78aa495da58356486aaa666cb57fd1James Dong                    kKeyAlbumArt, MetaData::TYPE_NONE,
17901552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                    buffer->data() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox);
1791515e855eae78aa495da58356486aaa666cb57fd1James Dong            }
1792515e855eae78aa495da58356486aaa666cb57fd1James Dong
1793515e855eae78aa495da58356486aaa666cb57fd1James Dong            *offset += chunk_size;
1794515e855eae78aa495da58356486aaa666cb57fd1James Dong            break;
1795515e855eae78aa495da58356486aaa666cb57fd1James Dong        }
1796515e855eae78aa495da58356486aaa666cb57fd1James Dong
17975d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('-', '-', '-', '-'):
17985d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        {
17995d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentMean.clear();
18005d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentName.clear();
18015d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentData.clear();
18025d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            *offset += chunk_size;
18035d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            break;
18045d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        }
18055d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen
180605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('s', 'i', 'd', 'x'):
180705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        {
180805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            parseSegmentIndex(data_offset, chunk_data_size);
180905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset += chunk_size;
181005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return UNKNOWN_ERROR; // stop parsing after sidx
181105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
181205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
181320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
181420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
181520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
181620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
181720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
181820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
181920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
182020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
182120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
182220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
182305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) {
182405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen  ALOGV("MPEG4Extractor::parseSegmentIndex");
182505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
182605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 12) {
182705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      return -EINVAL;
182805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
182905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
183005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
183105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) {
183205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
183305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
183405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
183505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t version = flags >> 24;
183605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    flags &= 0xffffff;
183705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
183805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx version %d", version);
183905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
184005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t referenceId;
184105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, &referenceId)) {
184205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
184305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
184405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
184505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t timeScale;
184605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 8, &timeScale)) {
184705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
184805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
184905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx refid/timescale: %d/%d", referenceId, timeScale);
185005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
185105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t earliestPresentationTime;
185205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t firstOffset;
185305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
185405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 12;
185505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 12;
185605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
185705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (version == 0) {
185805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 8) {
185905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
186005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
186105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t tmp;
186205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
186305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
186405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
186505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        earliestPresentationTime = tmp;
186605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset + 4, &tmp)) {
186705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
186805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
186905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        firstOffset = tmp;
187005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 8;
187105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 8;
187205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
187305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 16) {
187405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
187505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
187605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset, &earliestPresentationTime)) {
187705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
187805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
187905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset + 8, &firstOffset)) {
188005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
188105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
188205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 16;
188305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 16;
188405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
188505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx pres/off: %Ld/%Ld", earliestPresentationTime, firstOffset);
188605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
188705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 4) {
188805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
188905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
189005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
189105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint16_t referenceCount;
189205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt16(offset + 2, &referenceCount)) {
189305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
189405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
189505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 4;
189605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 4;
189705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("refcount: %d", referenceCount);
189805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
189905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < referenceCount * 12) {
190005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
190105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
190205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
190305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t total_duration = 0;
190405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    for (unsigned int i = 0; i < referenceCount; i++) {
190505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t d1, d2, d3;
190605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
190705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &d1) ||     // size
190805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            !mDataSource->getUInt32(offset + 4, &d2) || // duration
190905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            !mDataSource->getUInt32(offset + 8, &d3)) { // flags
191005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
191105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
191205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
191305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (d1 & 0x80000000) {
191405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGW("sub-sidx boxes not supported yet");
191505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
191605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool sap = d3 & 0x80000000;
191705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool saptype = d3 >> 28;
191805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!sap || saptype > 2) {
191905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGW("not a stream access point, or unsupported type");
192005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
192105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        total_duration += d2;
192205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 12;
192305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV(" item %d, %08x %08x %08x", i, d1, d2, d3);
192405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        SidxEntry se;
192505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        se.mSize = d1 & 0x7fffffff;
192605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        se.mDurationUs = 1000000LL * d2 / timeScale;
192705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mSidxEntries.add(se);
192805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
192905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
193005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mSidxDuration = total_duration * 1000000 / timeScale;
193105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("duration: %lld", mSidxDuration);
193205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
193305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t metaDuration;
193405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mLastTrack->meta->findInt64(kKeyDuration, &metaDuration) || metaDuration == 0) {
193505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mLastTrack->meta->setInt64(kKeyDuration, mSidxDuration);
193605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
193705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
193805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
193905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
194005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
194105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
1942ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huberstatus_t MPEG4Extractor::parseTrackHeader(
1943c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t data_offset, off64_t data_size) {
1944ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (data_size < 4) {
1945ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_MALFORMED;
1946ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1947ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1948ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint8_t version;
1949ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (mDataSource->readAt(data_offset, &version, 1) < 1) {
1950ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_IO;
1951ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1952ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1953ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    size_t dynSize = (version == 1) ? 36 : 24;
1954ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1955ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint8_t buffer[36 + 60];
1956ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1957c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    if (data_size != (off64_t)dynSize + 60) {
1958ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_MALFORMED;
1959ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1960ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1961ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (mDataSource->readAt(
1962ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber                data_offset, buffer, data_size) < (ssize_t)data_size) {
1963ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_IO;
1964ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1965ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1966ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint64_t ctime, mtime, duration;
1967ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t id;
1968ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1969ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (version == 1) {
1970ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        ctime = U64_AT(&buffer[4]);
1971ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mtime = U64_AT(&buffer[12]);
1972ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        id = U32_AT(&buffer[20]);
1973ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        duration = U64_AT(&buffer[28]);
197404022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen    } else if (version == 0) {
1975ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        ctime = U32_AT(&buffer[4]);
1976ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mtime = U32_AT(&buffer[8]);
1977ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        id = U32_AT(&buffer[12]);
1978ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        duration = U32_AT(&buffer[20]);
197904022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen    } else {
198004022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen        return ERROR_UNSUPPORTED;
1981ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1982ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1983ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    mLastTrack->meta->setInt32(kKeyTrackID, id);
1984ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1985ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    size_t matrixOffset = dynSize + 16;
1986ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a00 = U32_AT(&buffer[matrixOffset]);
1987ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a01 = U32_AT(&buffer[matrixOffset + 4]);
1988ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t dx = U32_AT(&buffer[matrixOffset + 8]);
1989ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a10 = U32_AT(&buffer[matrixOffset + 12]);
1990ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a11 = U32_AT(&buffer[matrixOffset + 16]);
1991ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t dy = U32_AT(&buffer[matrixOffset + 20]);
1992ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1993ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#if 0
1994df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("x' = %.2f * x + %.2f * y + %.2f",
1995ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber         a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f);
1996df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("y' = %.2f * x + %.2f * y + %.2f",
1997ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber         a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f);
1998ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#endif
1999ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2000ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t rotationDegrees;
2001ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2002ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    static const int32_t kFixedOne = 0x10000;
2003ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) {
2004ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        // Identity, no rotation
2005ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 0;
2006ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) {
2007ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 90;
2008ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) {
2009ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 270;
2010ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) {
2011ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 180;
2012ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else {
20135ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("We only support 0,90,180,270 degree rotation matrices");
2014ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 0;
2015ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2016ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2017ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (rotationDegrees != 0) {
2018ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees);
2019ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2020ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2021b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    // Handle presentation display size, which could be different
2022b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    // from the image size indicated by kKeyWidth and kKeyHeight.
2023ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t width = U32_AT(&buffer[dynSize + 52]);
2024ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t height = U32_AT(&buffer[dynSize + 56]);
2025b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    mLastTrack->meta->setInt32(kKeyDisplayWidth, width >> 16);
2026b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    mLastTrack->meta->setInt32(kKeyDisplayHeight, height >> 16);
2027ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2028ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    return OK;
2029ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber}
2030ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2031c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseMetaData(off64_t offset, size_t size) {
2032a1e21653e86d21a4ab0946ee2761b6f0163d5742Nick Kralevich    if (size < 4 || size == SIZE_MAX) {
203372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_MALFORMED;
203472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
203572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
203672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint8_t *buffer = new uint8_t[size + 1];
203772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (mDataSource->readAt(
203872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                offset, buffer, size) != (ssize_t)size) {
203972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        delete[] buffer;
204072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        buffer = NULL;
204172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
204272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_IO;
204372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
204472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
204572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t flags = U32_AT(buffer);
204672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
204772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t metadataKey = 0;
20485d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    char chunk[5];
20495d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    MakeFourCCString(mPath[4], chunk);
20505d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    ALOGV("meta: %s @ %lld", chunk, offset);
205172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    switch (mPath[4]) {
205272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'a', 'l', 'b'):
205372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
205472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbum;
205572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
205672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
205772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'A', 'R', 'T'):
205872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
205972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyArtist;
206072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
206172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
206266ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        case FOURCC('a', 'A', 'R', 'T'):
206366ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        {
206466ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            metadataKey = kKeyAlbumArtist;
206566ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            break;
206666ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        }
206772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'd', 'a', 'y'):
206872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
206972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyYear;
207072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
207172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
207272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'n', 'a', 'm'):
207372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
207472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyTitle;
207572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
207672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
207772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'w', 'r', 't'):
207872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
207972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyWriter;
208072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
208172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
208272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('c', 'o', 'v', 'r'):
208372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
208472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbumArt;
208572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
208672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
208772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('g', 'n', 'r', 'e'):
208872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
208972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyGenre;
209072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
209172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
209226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC(0xa9, 'g', 'e', 'n'):
209326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
209426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            metadataKey = kKeyGenre;
209526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
209626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
209711f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        case FOURCC('c', 'p', 'i', 'l'):
209811f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        {
209911f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            if (size == 9 && flags == 21) {
210011f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                char tmp[16];
210111f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                sprintf(tmp, "%d",
210211f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                        (int)buffer[size - 1]);
210311f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen
210411f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                mFileMetaData->setCString(kKeyCompilation, tmp);
210511f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            }
210611f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            break;
210711f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        }
210872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('t', 'r', 'k', 'n'):
210972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
211072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (size == 16 && flags == 0) {
211172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char tmp[16];
2112afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTrack = (uint16_t*)&buffer[10];
2113afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTotalTracks = (uint16_t*)&buffer[12];
2114afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                sprintf(tmp, "%d/%d", ntohs(*pTrack), ntohs(*pTotalTracks));
211572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
211672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
211772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
211872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
211972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
212026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC('d', 'i', 's', 'k'):
212126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
2122afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik            if ((size == 14 || size == 16) && flags == 0) {
212326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                char tmp[16];
2124afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pDisc = (uint16_t*)&buffer[10];
2125afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTotalDiscs = (uint16_t*)&buffer[12];
2126afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                sprintf(tmp, "%d/%d", ntohs(*pDisc), ntohs(*pTotalDiscs));
212726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
212826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(kKeyDiscNumber, tmp);
212926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            }
213026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
213126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
21325d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('-', '-', '-', '-'):
21335d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        {
21345d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            buffer[size] = '\0';
21355d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            switch (mPath[5]) {
21365d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('m', 'e', 'a', 'n'):
21375d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentMean.setTo((const char *)buffer + 4);
21385d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
21395d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('n', 'a', 'm', 'e'):
21405d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentName.setTo((const char *)buffer + 4);
21415d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
21425d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('d', 'a', 't', 'a'):
21435d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentData.setTo((const char *)buffer + 8);
21445d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
21455d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            }
21468c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
21478c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // Once we have a set of mean/name/data info, go ahead and process
21488c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // it to see if its something we are interested in.  Whether or not
21498c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // were are interested in the specific tag, make sure to clear out
21508c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // the set so we can be ready to process another tuple should one
21518c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // show up later in the file.
21528c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            if ((mLastCommentMean.length() != 0) &&
21538c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                (mLastCommentName.length() != 0) &&
21548c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                (mLastCommentData.length() != 0)) {
21558c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
21568c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                if (mLastCommentMean == "com.apple.iTunes"
21578c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        && mLastCommentName == "iTunSMPB") {
21588c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    int32_t delay, padding;
21598c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    if (sscanf(mLastCommentData,
21608c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                               " %*x %x %x %*x", &delay, &padding) == 2) {
21618c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
21628c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        mLastTrack->meta->setInt32(kKeyEncoderPadding, padding);
21638c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    }
21645d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                }
21658c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
21665d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentMean.clear();
21675d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentName.clear();
21685d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentData.clear();
21695d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            }
21705d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            break;
21715d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        }
217226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
217372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        default:
217472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
217572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
217672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
217772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (size >= 8 && metadataKey) {
217872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        if (metadataKey == kKeyAlbumArt) {
217972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setData(
218072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    kKeyAlbumArt, MetaData::TYPE_NONE,
218172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    buffer + 8, size - 8);
218272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else if (metadataKey == kKeyGenre) {
218372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (flags == 0) {
218426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // uint8_t genre code, iTunes genre codes are
218526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // the standard id3 codes, except they start
218626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // at 1 instead of 0 (e.g. Pop is 14, not 13)
218726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // We use standard id3 numbering, so subtract 1.
218826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                int genrecode = (int)buffer[size - 1];
218926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                genrecode--;
219026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                if (genrecode < 0) {
219126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                    genrecode = 255; // reserved for 'unknown genre'
219226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                }
219372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char genre[10];
219426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                sprintf(genre, "%d", genrecode);
219572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
219672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(metadataKey, genre);
219726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            } else if (flags == 1) {
219826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // custom genre string
219926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                buffer[size] = '\0';
220026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
220126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(
220226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                        metadataKey, (const char *)buffer + 8);
220372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
220472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else {
220572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            buffer[size] = '\0';
220672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
220772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(
220872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    metadataKey, (const char *)buffer + 8);
220972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
221072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
221172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
221272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    delete[] buffer;
221372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    buffer = NULL;
221472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
221572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return OK;
221672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
221772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
2218693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
221920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
222020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
2221693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return NULL;
222220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
222320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
222420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
222520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
222620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
2227693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber            return NULL;
222820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
222920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
223020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
223120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
223220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
223320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2234371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
2235371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
2236371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
2237371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
2238ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("getTrack called, pssh: %d", mPssh.size());
2239ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2240693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    return new MPEG4Source(
224105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            track->meta, mDataSource, track->timescale, track->sampleTable,
224205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mSidxEntries, mMoofOffset);
224320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
224420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2245bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber// static
2246bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) {
2247bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const char *mime;
2248bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    CHECK(track->meta->findCString(kKeyMIMEType, &mime));
2249bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2250bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    uint32_t type;
2251bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const void *data;
2252bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    size_t size;
2253bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
2254bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyAVCC, &type, &data, &size)
2255bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeAVCC) {
2256bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
2257bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
2258bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
2259bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
2260bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyESDS, &type, &data, &size)
2261bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeESDS) {
2262bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
2263bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
2264bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    }
2265bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2266169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber    if (!track->sampleTable->isValid()) {
2267169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        // Make sure we have all the metadata we need.
2268169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        return ERROR_MALFORMED;
2269169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber    }
2270169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber
2271bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    return OK;
2272bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber}
2273bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2274ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
2275ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        const void *esds_data, size_t esds_size) {
2276ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    ESDS esds(esds_data, esds_size);
227781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
227881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    uint8_t objectTypeIndication;
227981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
228081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return ERROR_MALFORMED;
228181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
228281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
228381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (objectTypeIndication == 0xe1) {
228481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        // This isn't MPEG4 audio at all, it's QCELP 14k...
228581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
228681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return OK;
228781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
228881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
2289633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong    if (objectTypeIndication  == 0x6b) {
2290633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // The media subtype is MP3 audio
2291633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // Our software MP3 audio decoder may not be able to handle
2292633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // packetized MP3 audio; for now, lets just return ERROR_UNSUPPORTED
229329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("MP3 track in MP4/3GPP file is not supported");
2294633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        return ERROR_UNSUPPORTED;
2295633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong    }
2296633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong
2297ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    const uint8_t *csd;
2298ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    size_t csd_size;
2299ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (esds.getCodecSpecificInfo(
2300ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                (const void **)&csd, &csd_size) != OK) {
2301ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
2302ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2303ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2304ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#if 0
2305ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    printf("ESD of size %d\n", csd_size);
2306ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    hexdump(csd, csd_size);
2307ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#endif
2308ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2309a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    if (csd_size == 0) {
2310a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // There's no further information, i.e. no codec specific data
2311a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // Let's assume that the information provided in the mpeg4 headers
2312a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // is accurate and hope for the best.
2313a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
2314a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        return OK;
2315a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    }
2316a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
2317ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (csd_size < 2) {
2318ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
2319ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2320ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
23213c836e7882e88de42e0e600627de433b61e78621Eric Laurent    static uint32_t kSamplingRate[] = {
23223c836e7882e88de42e0e600627de433b61e78621Eric Laurent        96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
23233c836e7882e88de42e0e600627de433b61e78621Eric Laurent        16000, 12000, 11025, 8000, 7350
23243c836e7882e88de42e0e600627de433b61e78621Eric Laurent    };
23253c836e7882e88de42e0e600627de433b61e78621Eric Laurent
2326aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    ABitReader br(csd, csd_size);
2327aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    uint32_t objectType = br.getBits(5);
2328ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2329aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    if (objectType == 31) {  // AAC-ELD => additional 6 bits
2330aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        objectType = 32 + br.getBits(6);
2331ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2332ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2333f590f948e6c0fe3c54008dd7802fd513f127792dEric Laurent    //keep AOT type
2334f590f948e6c0fe3c54008dd7802fd513f127792dEric Laurent    mLastTrack->meta->setInt32(kKeyAACAOT, objectType);
2335f590f948e6c0fe3c54008dd7802fd513f127792dEric Laurent
2336aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    uint32_t freqIndex = br.getBits(4);
2337aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
2338ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t sampleRate = 0;
2339ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t numChannels = 0;
2340ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (freqIndex == 15) {
2341ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        if (csd_size < 5) {
2342ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            return ERROR_MALFORMED;
2343ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
2344aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        sampleRate = br.getBits(24);
2345aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        numChannels = br.getBits(4);
2346ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    } else {
2347595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen        numChannels = br.getBits(4);
23483c836e7882e88de42e0e600627de433b61e78621Eric Laurent
23493c836e7882e88de42e0e600627de433b61e78621Eric Laurent        if (freqIndex == 13 || freqIndex == 14) {
23503c836e7882e88de42e0e600627de433b61e78621Eric Laurent            return ERROR_MALFORMED;
2351ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
2352ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
23533c836e7882e88de42e0e600627de433b61e78621Eric Laurent        sampleRate = kSamplingRate[freqIndex];
23543c836e7882e88de42e0e600627de433b61e78621Eric Laurent    }
2355595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen
23563c836e7882e88de42e0e600627de433b61e78621Eric Laurent    if (objectType == 5 || objectType == 29) { // SBR specific config per 14496-3 table 1.13
23573c836e7882e88de42e0e600627de433b61e78621Eric Laurent        uint32_t extFreqIndex = br.getBits(4);
23583c836e7882e88de42e0e600627de433b61e78621Eric Laurent        int32_t extSampleRate;
23593c836e7882e88de42e0e600627de433b61e78621Eric Laurent        if (extFreqIndex == 15) {
23603c836e7882e88de42e0e600627de433b61e78621Eric Laurent            if (csd_size < 8) {
2361595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen                return ERROR_MALFORMED;
2362595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen            }
23633c836e7882e88de42e0e600627de433b61e78621Eric Laurent            extSampleRate = br.getBits(24);
23643c836e7882e88de42e0e600627de433b61e78621Eric Laurent        } else {
23653c836e7882e88de42e0e600627de433b61e78621Eric Laurent            if (extFreqIndex == 13 || extFreqIndex == 14) {
23663c836e7882e88de42e0e600627de433b61e78621Eric Laurent                return ERROR_MALFORMED;
23673c836e7882e88de42e0e600627de433b61e78621Eric Laurent            }
23683c836e7882e88de42e0e600627de433b61e78621Eric Laurent            extSampleRate = kSamplingRate[extFreqIndex];
2369595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen        }
23703c836e7882e88de42e0e600627de433b61e78621Eric Laurent        //TODO: save the extension sampling rate value in meta data =>
23713c836e7882e88de42e0e600627de433b61e78621Eric Laurent        //      mLastTrack->meta->setInt32(kKeyExtSampleRate, extSampleRate);
2372ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2373ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2374ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (numChannels == 0) {
2375ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_UNSUPPORTED;
2376ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2377ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2378ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevSampleRate;
2379ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
2380ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2381ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevSampleRate != sampleRate) {
23823856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("mpeg4 audio sample rate different from previous setting. "
2383ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevSampleRate, sampleRate);
2384ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2385ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2386ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
2387ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2388ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevChannelCount;
2389ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
2390ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2391ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevChannelCount != numChannels) {
23923856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("mpeg4 audio channel count different from previous setting. "
2393ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevChannelCount, numChannels);
2394ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2395ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2396ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
2397ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2398ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    return OK;
2399ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber}
2400ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
240120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
240220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
240320111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::MPEG4Source(
240420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        const sp<MetaData> &format,
2405693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &dataSource,
240648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        int32_t timeScale,
240705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const sp<SampleTable> &sampleTable,
240805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        Vector<SidxEntry> &sidx,
240905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t firstMoofOffset)
241020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mFormat(format),
241120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDataSource(dataSource),
241248c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber      mTimescale(timeScale),
241320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSampleTable(sampleTable),
241420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCurrentSampleIndex(0),
241505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentFragmentIndex(0),
241605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mSegments(sidx),
241705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mFirstMoofOffset(firstMoofOffset),
241805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentMoofOffset(firstMoofOffset),
241905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentTime(0),
2420ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoAllocSize(0),
2421ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoSizes(NULL),
2422ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoOffsetsAllocSize(0),
2423ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoOffsets(NULL),
242420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mIsAVC(false),
24256064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber      mNALLengthSize(0),
242620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mStarted(false),
242720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mGroup(NULL),
242820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mBuffer(NULL),
2429dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber      mWantsNALFragments(false),
24300024245e134467d120b40099da16c467dc365e76Andreas Huber      mSrcBuffer(NULL) {
2431ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2432ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mFormat->findInt32(kKeyCryptoMode, &mCryptoMode);
243348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    mDefaultIVSize = 0;
2434ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mFormat->findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize);
2435ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t keytype;
2436ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    const void *key;
2437ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    size_t keysize;
2438ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mFormat->findData(kKeyCryptoKey, &keytype, &key, &keysize)) {
2439ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        CHECK(keysize <= 16);
2440ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memset(mCryptoKey, 0, 16);
2441ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memcpy(mCryptoKey, key, keysize);
2442ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2443ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
244420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
244520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mFormat->findCString(kKeyMIMEType, &mime);
2446dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(success);
244720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
244818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber    mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
24496064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
24506064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    if (mIsAVC) {
24516064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        uint32_t type;
24526064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const void *data;
24536064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t size;
24546064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(format->findData(kKeyAVCC, &type, &data, &size));
24556064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
24566064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const uint8_t *ptr = (const uint8_t *)data;
24576064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
24586064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(size >= 7);
2459ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
24606064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
24616064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        // The number of bytes used to encode the length of a NAL unit.
24626064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        mNALLengthSize = 1 + (ptr[4] & 3);
24636064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
246405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
246505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    CHECK(format->findInt32(kKeyTrackID, &mTrackId));
246605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
246705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mFirstMoofOffset != 0) {
246805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t offset = mFirstMoofOffset;
246905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        parseChunk(&offset);
247005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
247120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
247220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
247320111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::~MPEG4Source() {
247420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mStarted) {
247520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        stop();
247620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
2477ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    free(mCurrentSampleInfoSizes);
2478ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    free(mCurrentSampleInfoOffsets);
247920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
248020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
248120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::start(MetaData *params) {
24827b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
24837b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
2484dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(!mStarted);
248520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
248620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t val;
2487dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (params && params->findInt32(kKeyWantsNALFragments, &val)
248820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        && val != 0) {
2489dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = true;
249020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    } else {
2491dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = false;
249220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
249320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
249420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = new MediaBufferGroup;
249520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2496738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    int32_t max_size;
2497738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
249820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2499738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    mGroup->add_buffer(new MediaBuffer(max_size));
25000024245e134467d120b40099da16c467dc365e76Andreas Huber
25010024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = new uint8_t[max_size];
250220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
250320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = true;
250420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
250520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
250620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
250720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
250820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::stop() {
25097b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
25107b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
2511dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
251220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
251320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mBuffer != NULL) {
251420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->release();
251520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
251620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
251720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
25180024245e134467d120b40099da16c467dc365e76Andreas Huber    delete[] mSrcBuffer;
25190024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = NULL;
25200024245e134467d120b40099da16c467dc365e76Andreas Huber
252120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    delete mGroup;
252220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = NULL;
252320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
252420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = false;
252520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mCurrentSampleIndex = 0;
252620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
252720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
252820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
252920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
253005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseChunk(off64_t *offset) {
253105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t hdr[2];
253205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
253305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_IO;
253405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
253505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t chunk_size = ntohl(hdr[0]);
253605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t chunk_type = ntohl(hdr[1]);
253705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t data_offset = *offset + 8;
253805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
253905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (chunk_size == 1) {
254005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
254105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_IO;
254205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
254305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        chunk_size = ntoh64(chunk_size);
254405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        data_offset += 8;
254505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
254605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (chunk_size < 16) {
254705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            // The smallest valid chunk is 16 bytes long in this case.
254805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
254905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
255005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (chunk_size < 8) {
255105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // The smallest valid chunk is 8 bytes long.
255205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
255305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
255405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
255505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    char chunk[5];
255605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    MakeFourCCString(chunk_type, chunk);
255705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Source chunk %s @ %llx", chunk, *offset);
255805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
255905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t chunk_data_size = *offset + chunk_size - data_offset;
256005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
256105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    switch(chunk_type) {
256205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
256305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'r', 'a', 'f'):
256405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('m', 'o', 'o', 'f'): {
256505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t stop_offset = *offset + chunk_size;
256605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset = data_offset;
256705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            while (*offset < stop_offset) {
256805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err = parseChunk(offset);
256905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (err != OK) {
257005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return err;
257105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
257205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
257305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
2574ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // *offset points to the mdat box following this moof
257505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                parseChunk(offset); // doesn't actually parse it, just updates offset
257605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mNextMoofOffset = *offset;
257705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
257805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
257905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
258005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
258105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'f', 'h', 'd'): {
258205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err;
258305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if ((err = parseTrackFragmentHeader(data_offset, chunk_data_size)) != OK) {
258405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return err;
258505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
258605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                *offset += chunk_size;
258705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                break;
258805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
258905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
259005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'r', 'u', 'n'): {
259105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err;
259205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (mLastParsedTrackId == mTrackId) {
259305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    if ((err = parseTrackFragmentRun(data_offset, chunk_data_size)) != OK) {
259405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        return err;
259505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    }
259605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
259705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
259805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                *offset += chunk_size;
259905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                break;
260005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
260105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2602ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'a', 'i', 'z'): {
2603ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            status_t err;
2604ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((err = parseSampleAuxiliaryInformationSizes(data_offset, chunk_data_size)) != OK) {
2605ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return err;
2606ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
2607ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
2608ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
2609ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2610ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'a', 'i', 'o'): {
2611ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            status_t err;
2612ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((err = parseSampleAuxiliaryInformationOffsets(data_offset, chunk_data_size)) != OK) {
2613ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return err;
2614ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
2615ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
2616ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
2617ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2618ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2619ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('m', 'd', 'a', 't'): {
2620ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // parse DRM info if present
2621ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("MPEG4Source::parseChunk mdat");
2622ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // if saiz/saoi was previously observed, do something with the sampleinfos
2623ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
2624ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
2625ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2626ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
262705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        default: {
262805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset += chunk_size;
262905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
263005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
263105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
263205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
263305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
263405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2635ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissenstatus_t MPEG4Source::parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size) {
2636ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("parseSampleAuxiliaryInformationSizes");
2637ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // 14496-12 8.7.12
2638ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t version;
2639ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(
2640ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset, &version, sizeof(version))
2641ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            < (ssize_t)sizeof(version)) {
2642ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
2643ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2644ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2645ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (version != 0) {
2646ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_UNSUPPORTED;
2647ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2648ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
2649ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2650ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t flags;
2651ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt24(offset, &flags)) {
2652ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
2653ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2654ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 3;
2655ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2656ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (flags & 1) {
2657ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        uint32_t tmp;
2658ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
2659ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_MALFORMED;
2660ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2661ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentAuxInfoType = tmp;
2662ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        offset += 4;
2663ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
2664ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_MALFORMED;
2665ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2666ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentAuxInfoTypeParameter = tmp;
2667ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        offset += 4;
2668ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2669ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2670ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t defsize;
2671ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(offset, &defsize, 1) != 1) {
2672ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_MALFORMED;
2673ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2674ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mCurrentDefaultSampleInfoSize = defsize;
2675ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
2676ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2677ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t smplcnt;
2678ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &smplcnt)) {
2679ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_MALFORMED;
2680ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
268148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    mCurrentSampleInfoCount = smplcnt;
2682ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 4;
2683ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
268448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (mCurrentDefaultSampleInfoSize != 0) {
268548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        ALOGV("@@@@ using default sample info size of %d", mCurrentDefaultSampleInfoSize);
268648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return OK;
268748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
2688ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (smplcnt > mCurrentSampleInfoAllocSize) {
2689ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoSizes = (uint8_t*) realloc(mCurrentSampleInfoSizes, smplcnt);
2690ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoAllocSize = smplcnt;
2691ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2692ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2693ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mDataSource->readAt(offset, mCurrentSampleInfoSizes, smplcnt);
2694ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    return OK;
2695ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen}
2696ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2697ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissenstatus_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size) {
2698ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("parseSampleAuxiliaryInformationOffsets");
2699ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // 14496-12 8.7.13
2700ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t version;
2701ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(offset, &version, sizeof(version)) != 1) {
2702ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
2703ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2704ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
2705ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2706ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t flags;
2707ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt24(offset, &flags)) {
2708ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
2709ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2710ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 3;
2711ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2712ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t entrycount;
2713ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &entrycount)) {
2714ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
2715ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2716ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 4;
2717ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2718ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (entrycount > mCurrentSampleInfoOffsetsAllocSize) {
2719ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoOffsets = (uint64_t*) realloc(mCurrentSampleInfoOffsets, entrycount * 8);
2720ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoOffsetsAllocSize = entrycount;
2721ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2722ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mCurrentSampleInfoOffsetCount = entrycount;
2723ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2724ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < entrycount; i++) {
2725ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (version == 0) {
2726ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t tmp;
2727ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (!mDataSource->getUInt32(offset, &tmp)) {
2728ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
2729ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
2730ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mCurrentSampleInfoOffsets[i] = tmp;
2731ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset += 4;
2732ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        } else {
2733ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint64_t tmp;
2734ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (!mDataSource->getUInt64(offset, &tmp)) {
2735ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
2736ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
2737ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mCurrentSampleInfoOffsets[i] = tmp;
2738ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset += 8;
2739ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2740ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2741ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2742ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // parse clear/encrypted data
2743ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2744ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    off64_t drmoffset = mCurrentSampleInfoOffsets[0]; // from moof
2745ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2746ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    drmoffset += mCurrentMoofOffset;
2747ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int ivlength;
2748ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    CHECK(mFormat->findInt32(kKeyCryptoDefaultIVSize, &ivlength));
274948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
275048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    // read CencSampleAuxiliaryDataFormats
2751ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mCurrentSampleInfoCount; i++) {
2752ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Sample *smpl = &mCurrentSamples.editItemAt(i);
2753ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2754ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memset(smpl->iv, 0, 16);
2755ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (mDataSource->readAt(drmoffset, smpl->iv, ivlength) != ivlength) {
2756ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_IO;
2757ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2758ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2759ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        drmoffset += ivlength;
2760ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
276148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        int32_t smplinfosize = mCurrentDefaultSampleInfoSize;
276248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        if (smplinfosize == 0) {
276348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smplinfosize = mCurrentSampleInfoSizes[i];
2764ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
276548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        if (smplinfosize > ivlength) {
276648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint16_t numsubsamples;
276748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (!mDataSource->getUInt16(drmoffset, &numsubsamples)) {
2768ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
2769ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
2770ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            drmoffset += 2;
277148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            for (size_t j = 0; j < numsubsamples; j++) {
277248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                uint16_t numclear;
277348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                uint32_t numencrypted;
277448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                if (!mDataSource->getUInt16(drmoffset, &numclear)) {
277548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                    return ERROR_IO;
277648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                }
277748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                drmoffset += 2;
277848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                if (!mDataSource->getUInt32(drmoffset, &numencrypted)) {
277948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                    return ERROR_IO;
278048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                }
278148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                drmoffset += 4;
278248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->clearsizes.add(numclear);
278348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->encryptedsizes.add(numencrypted);
2784ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
278548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        } else {
278648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smpl->clearsizes.add(0);
278748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smpl->encryptedsizes.add(smpl->size);
2788ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2789ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2790ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2791ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2792ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    return OK;
2793ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen}
2794ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
279505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentHeader(off64_t offset, off64_t size) {
279605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
279705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 8) {
279805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
279905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
280005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
280105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
2802ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags
280305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
280405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
280505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
280605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & 0xff000000) {
280705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
280805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
280905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
281005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, (uint32_t*)&mLastParsedTrackId)) {
281105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
281205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
281305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
281405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mLastParsedTrackId != mTrackId) {
281505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // this is not the right track, skip it
281605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
281705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
281805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
281905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mFlags = flags;
282005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mTrackID = mLastParsedTrackId;
282105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 8;
282205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 8;
282305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
282405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("fragment header: %08x %08x", flags, mTrackFragmentHeaderInfo.mTrackID);
282505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
282605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent) {
282705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 8) {
282805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
282905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
283005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
283105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset, &mTrackFragmentHeaderInfo.mBaseDataOffset)) {
283205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
283305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
283405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 8;
283505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 8;
283605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
283705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
283805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent) {
283905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
284005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
284105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
284205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
284305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mSampleDescriptionIndex)) {
284405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
284505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
284605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
284705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
284805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
284905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
285005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
285105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
285205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
285305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
285405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
285505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleDuration)) {
285605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
285705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
285805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
285905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
286005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
286105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
286205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
286305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
286405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
286505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
286605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
286705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleSize)) {
286805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
286905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
287005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
287105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
287205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
287305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
287405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
287505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
287605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
287705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
287805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
287905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleFlags)) {
288005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
288105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
288205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
288305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
288405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
288505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
288605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!(flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent)) {
288705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mTrackFragmentHeaderInfo.mBaseDataOffset = mCurrentMoofOffset;
288805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
288905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
289005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mDataOffset = 0;
289105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
289205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
289305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
289405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentRun(off64_t offset, off64_t size) {
289505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
289605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Extractor::parseTrackFragmentRun");
289705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 8) {
289805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
289905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
290005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
290105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    enum {
290205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kDataOffsetPresent                  = 0x01,
290305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kFirstSampleFlagsPresent            = 0x04,
290405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleDurationPresent              = 0x100,
290505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleSizePresent                  = 0x200,
290605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleFlagsPresent                 = 0x400,
290705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleCompositionTimeOffsetPresent = 0x800,
290805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
290905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
291005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
291105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) {
291205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
291305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
291405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("fragment run flags: %08x", flags);
291505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
291605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & 0xff000000) {
291705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
291805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
291905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
292005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if ((flags & kFirstSampleFlagsPresent) && (flags & kSampleFlagsPresent)) {
292105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // These two shall not be used together.
292205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
292305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
292405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
292505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t sampleCount;
292605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, &sampleCount)) {
292705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
292805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
292905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 8;
293005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 8;
293105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
293205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t dataOffset = mTrackFragmentHeaderInfo.mDataOffset;
293305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
293405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t firstSampleFlags = 0;
293505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
293605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kDataOffsetPresent) {
293705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
293805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
293905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
294005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
294105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int32_t dataOffsetDelta;
294205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, (uint32_t*)&dataOffsetDelta)) {
294305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
294405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
294505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
294605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        dataOffset = mTrackFragmentHeaderInfo.mBaseDataOffset + dataOffsetDelta;
294705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
294805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
294905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
295005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
295105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
295205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kFirstSampleFlagsPresent) {
295305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
295405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
295505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
295605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
295705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &firstSampleFlags)) {
295805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
295905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
296005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
296105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
296205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
296305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
296405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t sampleDuration = 0, sampleSize = 0, sampleFlags = 0,
296505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen             sampleCtsOffset = 0;
296605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
296705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size_t bytesPerSample = 0;
296805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleDurationPresent) {
296905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
297005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
297105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
297205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration;
297305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
297405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration;
297505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
297605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
297705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleSizePresent) {
297805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
297905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
298005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
298105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
298205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
298305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
298405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
298505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
298605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleFlagsPresent) {
298705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
298805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
298905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
299005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
299105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
299205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
299305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
299405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
299505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleCompositionTimeOffsetPresent) {
299605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
299705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
299805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleCtsOffset = 0;
299905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
300005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
300105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < sampleCount * bytesPerSample) {
300205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
300305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
300405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
300505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Sample tmp;
300605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    for (uint32_t i = 0; i < sampleCount; ++i) {
300705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleDurationPresent) {
300805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleDuration)) {
300905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
301005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
301105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
301205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
301305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
301405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleSizePresent) {
301505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleSize)) {
301605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
301705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
301805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
301905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
302005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
302105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleFlagsPresent) {
302205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleFlags)) {
302305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
302405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
302505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
302605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
302705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
302805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleCompositionTimeOffsetPresent) {
302905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleCtsOffset)) {
303005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
303105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
303205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
303305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
303405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3035ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        ALOGV("adding sample %d at offset 0x%08llx, size %u, duration %u, "
3036ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen              " flags 0x%08x", i + 1,
303705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dataOffset, sampleSize, sampleDuration,
303805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                (flags & kFirstSampleFlagsPresent) && i == 0
303905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ? firstSampleFlags : sampleFlags);
304005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.offset = dataOffset;
304105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.size = sampleSize;
304205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.duration = sampleDuration;
304305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentSamples.add(tmp);
304405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
304505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        dataOffset += sampleSize;
304605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
304705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
304805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mDataOffset = dataOffset;
304905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
305005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
305105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
305205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
305320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> MPEG4Source::getFormat() {
30547b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
30557b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
305620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return mFormat;
305720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
305820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30596064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const {
30606064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    switch (mNALLengthSize) {
30616064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 1:
30626064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return *data;
30636064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 2:
30646064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U16_AT(data);
30656064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 3:
30666064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return ((size_t)data[0] << 16) | U16_AT(&data[1]);
30676064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 4:
30686064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U32_AT(data);
30696064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
30706064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
30716064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // This cannot happen, mNALLengthSize springs to life by adding 1 to
30726064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // a 2-bit integer.
30736064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    CHECK(!"Should not be here.");
30746064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
30756064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    return 0;
30766064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber}
30776064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
307820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::read(
307920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
30807b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
30817b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
3082dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
308320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
308405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mFirstMoofOffset > 0) {
308505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return fragmentedRead(out, options);
308605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
308705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
308820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *out = NULL;
308920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3090abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    int64_t targetSampleTimeUs = -1;
3091abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
309220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t seekTimeUs;
3093abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
3094abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
3095abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t findFlags = 0;
3096abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        switch (mode) {
3097abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_PREVIOUS_SYNC:
3098abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagBefore;
3099abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3100abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_NEXT_SYNC:
3101abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagAfter;
3102abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3103abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST_SYNC:
3104abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST:
3105abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagClosest;
3106abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3107abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            default:
3108abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                CHECK(!"Should not be here.");
3109abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3110abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3111abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
311220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        uint32_t sampleIndex;
3113abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        status_t err = mSampleTable->findSampleAtTime(
311420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                seekTimeUs * mTimescale / 1000000,
3115abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                &sampleIndex, findFlags);
3116abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3117abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
3118abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // We found the closest sample already, now we want the sync
3119abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // sample preceding it (or the sample itself of course), even
3120abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // if the subsequent sync sample is closer.
3121abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            findFlags = SampleTable::kFlagBefore;
3122abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3123abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3124abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleIndex;
3125abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (err == OK) {
3126abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            err = mSampleTable->findSyncSampleNear(
3127abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    sampleIndex, &syncSampleIndex, findFlags);
3128abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
312920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3130788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        uint32_t sampleTime;
3131788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        if (err == OK) {
3132788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber            err = mSampleTable->getMetaDataForSample(
3133788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber                    sampleIndex, NULL, NULL, &sampleTime);
3134788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        }
3135788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber
313620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (err != OK) {
31375295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            if (err == ERROR_OUT_OF_RANGE) {
31385295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // An attempt to seek past the end of the stream would
31395295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // normally cause this ERROR_OUT_OF_RANGE error. Propagating
31405295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // this all the way to the MediaPlayer would cause abnormal
31415295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // termination. Legacy behaviour appears to be to behave as if
31425295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // we had seeked to the end of stream, ending normally.
31435295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                err = ERROR_END_OF_STREAM;
31445295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            }
314505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("end of stream");
314620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return err;
314720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
314820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3149abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
3150abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
3151abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3152abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3153abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#if 0
3154abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleTime;
3155abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
3156abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    syncSampleIndex, NULL, NULL, &syncSampleTime));
3157abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3158df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("seek to time %lld us => sample at time %lld us, "
3159abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             "sync sample at time %lld us",
3160abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             seekTimeUs,
3161abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             sampleTime * 1000000ll / mTimescale,
3162abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             syncSampleTime * 1000000ll / mTimescale);
3163abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#endif
3164abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3165abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        mCurrentSampleIndex = syncSampleIndex;
316620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mBuffer != NULL) {
316720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
316820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
316920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
317020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
317120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // fall through
317220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
317320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3174c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset;
31750024245e134467d120b40099da16c467dc365e76Andreas Huber    size_t size;
31764678a6dc5f09008481524949a9667af5a6190374Andreas Huber    uint32_t cts;
31778bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    bool isSyncSample;
3178dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool newBuffer = false;
3179dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (mBuffer == NULL) {
3180dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        newBuffer = true;
318120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3182c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        status_t err =
3183c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber            mSampleTable->getMetaDataForSample(
31844678a6dc5f09008481524949a9667af5a6190374Andreas Huber                    mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample);
318520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3186dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
3187dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
3188dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3189dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3190dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        err = mGroup->acquire_buffer(&mBuffer);
3191c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
3192dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
3193ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            CHECK(mBuffer == NULL);
3194dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
3195dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
31960024245e134467d120b40099da16c467dc365e76Andreas Huber    }
319720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3198dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (!mIsAVC || mWantsNALFragments) {
3199dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (newBuffer) {
3200dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ssize_t num_bytes_read =
320134769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
3202dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3203dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            if (num_bytes_read < (ssize_t)size) {
3204dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer->release();
3205dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer = NULL;
3206dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3207dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                return ERROR_IO;
3208dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            }
3209dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
32107b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber            CHECK(mBuffer != NULL);
3211dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->set_range(0, size);
3212dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->meta_data()->clear();
321348c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mBuffer->meta_data()->setInt64(
32144678a6dc5f09008481524949a9667af5a6190374Andreas Huber                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
3215abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3216abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            if (targetSampleTimeUs >= 0) {
3217abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                mBuffer->meta_data()->setInt64(
3218abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                        kKeyTargetTime, targetSampleTimeUs);
3219abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            }
3220abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
32218bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            if (isSyncSample) {
32228bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
32238bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            }
32248bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
3225dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ++mCurrentSampleIndex;
3226dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3227dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3228dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (!mIsAVC) {
3229dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            *out = mBuffer;
3230dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
3231dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3232dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return OK;
3233dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3234dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3235dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Each NAL unit is split up into its constituent fragments and
3236dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // each one of them returned in its own buffer.
3237dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
32386064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(mBuffer->range_length() >= mNALLengthSize);
3239dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3240dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        const uint8_t *src =
3241dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
3242dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
32436064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t nal_size = parseNALSize(src);
3244e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
324529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("incomplete NAL unit.");
3246e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3247e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer->release();
3248e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer = NULL;
3249e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3250e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            return ERROR_MALFORMED;
3251e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        }
3252dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3253dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        MediaBuffer *clone = mBuffer->clone();
32547b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(clone != NULL);
32556064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
3256dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
32577b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(mBuffer != NULL);
3258dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mBuffer->set_range(
32596064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_offset() + mNALLengthSize + nal_size,
32606064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_length() - mNALLengthSize - nal_size);
3261dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3262dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (mBuffer->range_length() == 0) {
3263dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->release();
3264dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
3265dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3266dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3267dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        *out = clone;
3268dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3269dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        return OK;
3270dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    } else {
3271dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Whole NAL units are returned but each fragment is prefixed by
3272dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // the start code (0x00 00 00 01).
3273dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        ssize_t num_bytes_read = 0;
3274dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        int32_t drm = 0;
3275dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
3276dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (usesDRM) {
3277dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            num_bytes_read =
3278dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
3279dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
3280dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
3281dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
328220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
328320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (num_bytes_read < (ssize_t)size) {
328420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
328520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
328620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3287dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return ERROR_IO;
328820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
328920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3290dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (usesDRM) {
3291dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK(mBuffer != NULL);
3292dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            mBuffer->set_range(0, size);
32936064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
3294dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
3295dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            uint8_t *dstData = (uint8_t *)mBuffer->data();
3296dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size_t srcOffset = 0;
3297dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size_t dstOffset = 0;
3298e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3299dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            while (srcOffset < size) {
330067a30ebfe785f7cd5ecfb0d2fb487e54536a3d48Lajos Molnar                bool isMalFormed = !isInRange(0u, size, srcOffset, mNALLengthSize);
330134fe252c89e33572d01fea981b58d7b115e76164James Dong                size_t nalLength = 0;
330234fe252c89e33572d01fea981b58d7b115e76164James Dong                if (!isMalFormed) {
330334fe252c89e33572d01fea981b58d7b115e76164James Dong                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
330434fe252c89e33572d01fea981b58d7b115e76164James Dong                    srcOffset += mNALLengthSize;
330567a30ebfe785f7cd5ecfb0d2fb487e54536a3d48Lajos Molnar                    isMalFormed = !isInRange(0u, size, srcOffset, nalLength);
330634fe252c89e33572d01fea981b58d7b115e76164James Dong                }
3307e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
330834fe252c89e33572d01fea981b58d7b115e76164James Dong                if (isMalFormed) {
330929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                    ALOGE("Video is malformed");
3310dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    mBuffer->release();
3311dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    mBuffer = NULL;
3312dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return ERROR_MALFORMED;
3313dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
3314dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
3315dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                if (nalLength == 0) {
3316dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    continue;
3317dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
3318dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3319dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                CHECK(dstOffset + 4 <= mBuffer->size());
3320dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3321dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3322dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3323dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3324dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 1;
3325dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
3326dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                srcOffset += nalLength;
3327dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstOffset += nalLength;
3328dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
3329dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK_EQ(srcOffset, size);
3330dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK(mBuffer != NULL);
3331dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            mBuffer->set_range(0, dstOffset);
3332dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3333dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
333420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->meta_data()->clear();
333548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        mBuffer->meta_data()->setInt64(
33364678a6dc5f09008481524949a9667af5a6190374Andreas Huber                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
3337abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3338abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (targetSampleTimeUs >= 0) {
3339abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            mBuffer->meta_data()->setInt64(
3340abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    kKeyTargetTime, targetSampleTimeUs);
3341abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3342abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
33438bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        if (isSyncSample) {
33448bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
33458bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        }
33468bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
334720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        ++mCurrentSampleIndex;
334820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
334920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        *out = mBuffer;
335020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
335120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
335220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
335320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
335420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
335520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
335605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::fragmentedRead(
335705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MediaBuffer **out, const ReadOptions *options) {
335805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
335905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Source::fragmentedRead");
336005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
336105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    CHECK(mStarted);
336205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
336305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    *out = NULL;
336405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
336505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t targetSampleTimeUs = -1;
336605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
336705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t seekTimeUs;
336805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ReadOptions::SeekMode mode;
336905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
337005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
337105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int numSidxEntries = mSegments.size();
337205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (numSidxEntries != 0) {
337305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            int64_t totalTime = 0;
337405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t totalOffset = mFirstMoofOffset;
337505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            for (int i = 0; i < numSidxEntries; i++) {
337605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                const SidxEntry *se = &mSegments[i];
337705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (totalTime + se->mDurationUs > seekTimeUs) {
337805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    // The requested time is somewhere in this segment
337905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    if ((mode == ReadOptions::SEEK_NEXT_SYNC) ||
338005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        (mode == ReadOptions::SEEK_CLOSEST_SYNC &&
338105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        (seekTimeUs - totalTime) > (totalTime + se->mDurationUs - seekTimeUs))) {
338205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        // requested next sync, or closest sync and it was closer to the end of
338305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        // this segment
338405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        totalTime += se->mDurationUs;
338505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        totalOffset += se->mSize;
338605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    }
338705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    break;
338805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
338905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                totalTime += se->mDurationUs;
339005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                totalOffset += se->mSize;
339105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
339205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentMoofOffset = totalOffset;
339305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentSamples.clear();
339405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentSampleIndex = 0;
339505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        parseChunk(&totalOffset);
339605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentTime = totalTime * mTimescale / 1000000ll;
339705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
339805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
339905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer != NULL) {
340005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
340105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
340205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
340305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
340405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // fall through
340505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
340605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
340705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t offset = 0;
340805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size_t size;
340905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t cts = 0;
341005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    bool isSyncSample = false;
341105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    bool newBuffer = false;
341205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mBuffer == NULL) {
341305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        newBuffer = true;
341405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
341505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mCurrentSampleIndex >= mCurrentSamples.size()) {
341605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            // move to next fragment
341705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            Sample lastSample = mCurrentSamples[mCurrentSamples.size() - 1];
341805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t nextMoof = mNextMoofOffset; // lastSample.offset + lastSample.size;
341905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentMoofOffset = nextMoof;
342005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentSamples.clear();
342105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentSampleIndex = 0;
342205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            parseChunk(&nextMoof);
342305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (mCurrentSampleIndex >= mCurrentSamples.size()) {
342405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return ERROR_END_OF_STREAM;
342505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
342605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
342705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
342805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
342905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset = smpl->offset;
343005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size = smpl->size;
343105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        cts = mCurrentTime;
343205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentTime += smpl->duration;
343305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        isSyncSample = (mCurrentSampleIndex == 0); // XXX
343405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
343505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        status_t err = mGroup->acquire_buffer(&mBuffer);
343605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
343705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (err != OK) {
343805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer == NULL);
343905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("acquire_buffer returned %d", err);
344005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return err;
344105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
344205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
344305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
344448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
344548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    const sp<MetaData> bufmeta = mBuffer->meta_data();
344648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    bufmeta->clear();
344748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (smpl->encryptedsizes.size()) {
344848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // store clear/encrypted lengths in metadata
344948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyPlainSizes, 0,
345048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->clearsizes.array(), smpl->clearsizes.size() * 4);
345148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyEncryptedSizes, 0,
345248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
345348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
345448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
345548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setInt32(kKeyCryptoMode, mCryptoMode);
345648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16);
345748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
345848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
345905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mIsAVC || mWantsNALFragments) {
346005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (newBuffer) {
346105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ssize_t num_bytes_read =
346205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
346305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
346405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (num_bytes_read < (ssize_t)size) {
346505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->release();
346605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer = NULL;
346705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
346805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                ALOGV("i/o error");
346905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_IO;
347005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
347105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
347205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
347305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, size);
347405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt64(
347505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
347605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
347705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (targetSampleTimeUs >= 0) {
347805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->meta_data()->setInt64(
347905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        kKeyTargetTime, targetSampleTimeUs);
348005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
348105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
348205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (isSyncSample) {
348305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
348405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
348505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
348605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ++mCurrentSampleIndex;
348705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
348805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
348905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mIsAVC) {
349005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *out = mBuffer;
349105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
349205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
349305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return OK;
349405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
349505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
349605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // Each NAL unit is split up into its constituent fragments and
349705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // each one of them returned in its own buffer.
349805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
349905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(mBuffer->range_length() >= mNALLengthSize);
350005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
350105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const uint8_t *src =
350205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
350305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
350405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size_t nal_size = parseNALSize(src);
350505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
350605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGE("incomplete NAL unit.");
350705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
350805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
350905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
351005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
351105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
351205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
351305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
351405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MediaBuffer *clone = mBuffer->clone();
351505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(clone != NULL);
351605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
351705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
351805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(mBuffer != NULL);
351905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer->set_range(
352005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->range_offset() + mNALLengthSize + nal_size,
352105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->range_length() - mNALLengthSize - nal_size);
352205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
352305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer->range_length() == 0) {
352405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
352505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
352605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
352705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
352805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        *out = clone;
352905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
353005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
353105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
353205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV("whole NAL");
353305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // Whole NAL units are returned but each fragment is prefixed by
353405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // the start code (0x00 00 00 01).
353505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ssize_t num_bytes_read = 0;
353605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int32_t drm = 0;
353705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
353805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (usesDRM) {
353905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            num_bytes_read =
354005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
354105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else {
354205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
354305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
354405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
354505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (num_bytes_read < (ssize_t)size) {
354605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
354705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
354805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
354905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("i/o error");
355005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_IO;
355105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
355205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
355305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (usesDRM) {
355405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
355505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, size);
355605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
355705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else {
355805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            uint8_t *dstData = (uint8_t *)mBuffer->data();
355905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            size_t srcOffset = 0;
356005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            size_t dstOffset = 0;
356105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
356205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            while (srcOffset < size) {
356367a30ebfe785f7cd5ecfb0d2fb487e54536a3d48Lajos Molnar                bool isMalFormed = !isInRange(0u, size, srcOffset, mNALLengthSize);
356405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                size_t nalLength = 0;
356505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (!isMalFormed) {
356605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
356705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    srcOffset += mNALLengthSize;
356867a30ebfe785f7cd5ecfb0d2fb487e54536a3d48Lajos Molnar                    isMalFormed = !isInRange(0u, size, srcOffset, nalLength);
356905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
357005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
357105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (isMalFormed) {
357205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ALOGE("Video is malformed");
357305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    mBuffer->release();
357405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    mBuffer = NULL;
357505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return ERROR_MALFORMED;
357605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
357705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
357805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (nalLength == 0) {
357905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    continue;
358005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
358105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
358205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                CHECK(dstOffset + 4 <= mBuffer->size());
358305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
358405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
358505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
358605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
358705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 1;
358805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
358905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                srcOffset += nalLength;
359005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstOffset += nalLength;
359105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
359205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK_EQ(srcOffset, size);
359305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
359405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, dstOffset);
359505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
359605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
359705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer->meta_data()->setInt64(
359805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
359905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
360005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (targetSampleTimeUs >= 0) {
360105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt64(
360205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    kKeyTargetTime, targetSampleTimeUs);
360305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
360405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
360505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (isSyncSample) {
360605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
360705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
360805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
360905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ++mCurrentSampleIndex;
361005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
361105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        *out = mBuffer;
361205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer = NULL;
361305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
361405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
361505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
361605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
361705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3618bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas HuberMPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix(
3619bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        const char *mimePrefix) {
3620bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    for (Track *track = mFirstTrack; track != NULL; track = track->next) {
3621bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        const char *mime;
3622bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        if (track->meta != NULL
3623bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                && track->meta->findCString(kKeyMIMEType, &mime)
3624bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) {
3625bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber            return track;
3626bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        }
3627bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    }
3628bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber
3629bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    return NULL;
3630bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber}
3631bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber
36321b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool LegacySniffMPEG4(
3633693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
363420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[8];
363520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
363634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    ssize_t n = source->readAt(4, header, sizeof(header));
363720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (n < (ssize_t)sizeof(header)) {
363820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return false;
363920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
364020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
364120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
3642b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8)
3643b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8)
36440dba73763a04d39faf999dcc5ef12af3c99535a7Andreas Huber        || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
3645ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
3646983b449a27b5fa91eca82ede5204b4341899be62Andreas Huber        || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
364718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
36485a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        *confidence = 0.4;
364920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
365020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return true;
365120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
365220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
365320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return false;
365420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
365520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36561b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool isCompatibleBrand(uint32_t fourcc) {
36571b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    static const uint32_t kCompatibleBrands[] = {
36581b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', 'm'),
36591b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', '2'),
36601b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('a', 'v', 'c', '1'),
36611b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('3', 'g', 'p', '4'),
36621b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '1'),
36631b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '2'),
36644cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong
36654cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        // Won't promise that the following file types can be played.
36664cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        // Just give these file types a chance.
36674cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        FOURCC('q', 't', ' ', ' '),  // Apple's QuickTime
36684cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        FOURCC('M', 'S', 'N', 'V'),  // Sony's PSP
366958fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber
367058fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber        FOURCC('3', 'g', '2', 'a'),  // 3GPP2
367158fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber        FOURCC('3', 'g', '2', 'b'),
36721b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    };
36731b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
36741b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    for (size_t i = 0;
36751b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]);
36761b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         ++i) {
36771b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        if (kCompatibleBrands[i] == fourcc) {
36781b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            return true;
36791b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
36801b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
36811b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
36821b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
36831b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
36841b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
36851b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// Attempt to actually parse the 'ftyp' atom and determine if a suitable
36861b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// compatible brand is present.
3687a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// Also try to identify where this file's metadata ends
3688a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// (end of the 'moov' atom) and report it to the caller as part of
3689a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// the metadata.
36901b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool BetterSniffMPEG4(
3691a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
3692a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        sp<AMessage> *meta) {
3693a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    // We scan up to 128 bytes to identify this file as an MP4.
3694a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    static const off64_t kMaxScanOffset = 128ll;
36951b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
3696a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    off64_t offset = 0ll;
3697a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    bool foundGoodFileType = false;
3698a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    off64_t moovAtomEndOffset = -1ll;
3699a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    bool done = false;
37001b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
3701a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    while (!done && offset < kMaxScanOffset) {
3702a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint32_t hdr[2];
3703a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        if (source->readAt(offset, hdr, 8) < 8) {
3704a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            return false;
3705a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        }
3706a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3707a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint64_t chunkSize = ntohl(hdr[0]);
3708a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint32_t chunkType = ntohl(hdr[1]);
3709a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        off64_t chunkDataOffset = offset + 8;
3710a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3711a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        if (chunkSize == 1) {
3712a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            if (source->readAt(offset + 8, &chunkSize, 8) < 8) {
37131b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                return false;
37141b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
37151b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
3716a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            chunkSize = ntoh64(chunkSize);
3717a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            chunkDataOffset += 8;
3718a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3719a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            if (chunkSize < 16) {
3720a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                // The smallest valid chunk is 16 bytes long in this case.
3721a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                return false;
3722a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            }
3723a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        } else if (chunkSize < 8) {
3724a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            // The smallest valid chunk is 8 bytes long.
3725a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            return false;
3726a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        }
3727a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3728a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        off64_t chunkDataSize = offset + chunkSize - chunkDataOffset;
3729a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
373005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        char chunkstring[5];
373105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MakeFourCCString(chunkType, chunkstring);
373205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV("saw chunk type %s, size %lld @ %lld", chunkstring, chunkSize, offset);
3733a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        switch (chunkType) {
3734a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            case FOURCC('f', 't', 'y', 'p'):
3735a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            {
3736a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                if (chunkDataSize < 8) {
3737a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    return false;
3738a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
3739a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3740a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4;
3741a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
3742a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (i == 1) {
3743a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        // Skip this index, it refers to the minorVersion,
3744a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        // not a brand.
3745a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        continue;
3746a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
3747a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3748a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    uint32_t brand;
3749a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (source->readAt(
3750a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                                chunkDataOffset + 4 * i, &brand, 4) < 4) {
3751a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        return false;
3752a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
3753a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3754a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    brand = ntohl(brand);
3755a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3756a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (isCompatibleBrand(brand)) {
3757a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        foundGoodFileType = true;
3758a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        break;
3759a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
3760a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
3761a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3762a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                if (!foundGoodFileType) {
3763a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    return false;
3764a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
3765a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
37661b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                break;
37671b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
3768a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3769a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            case FOURCC('m', 'o', 'o', 'v'):
3770a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            {
3771a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                moovAtomEndOffset = offset + chunkSize;
3772a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3773a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                done = true;
3774a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                break;
3775a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            }
3776a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3777a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            default:
3778a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                break;
37791b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
3780a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3781a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        offset += chunkSize;
37821b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
37831b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
3784a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (!foundGoodFileType) {
37851b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return false;
37861b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
37871b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
37881b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
37895a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber    *confidence = 0.4f;
37901b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
3791a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (moovAtomEndOffset >= 0) {
3792a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        *meta = new AMessage;
3793a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        (*meta)->setInt64("meta-data-size", moovAtomEndOffset);
3794a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3795456caf3f5f0af673dc120c17c23635f40d8f5ac2Andreas Huber        ALOGV("found metadata size: %lld", moovAtomEndOffset);
3796a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    }
3797a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
37981b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return true;
37991b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
38001b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
38011b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberbool SniffMPEG4(
38025a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
3803a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        sp<AMessage> *meta) {
3804a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (BetterSniffMPEG4(source, mimeType, confidence, meta)) {
38051b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
38061b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
38071b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
38081b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    if (LegacySniffMPEG4(source, mimeType, confidence)) {
38095ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Identified supported mpeg4 through LegacySniffMPEG4.");
38101b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
38111b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
38121b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
38131b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
38141b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
38151b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
381620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
3817