MPEG4Extractor.cpp revision 04022b34d2b97938b0926ab62e6c283418da3bba
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>
3420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBufferGroup.h>
3618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
3720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/String8.h>
4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Source : public MediaSource {
4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Caller retains ownership of both "dataSource" and "sampleTable".
46693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    MPEG4Source(const sp<MetaData> &format,
47693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber                const sp<DataSource> &dataSource,
4848c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                int32_t timeScale,
4905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                const sp<SampleTable> &sampleTable,
5005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                Vector<SidxEntry> &sidx,
5105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                off64_t firstMoofOffset);
5220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t start(MetaData *params = NULL);
5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t stop();
5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual sp<MetaData> getFormat();
5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL);
5905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    virtual status_t fragmentedRead(MediaBuffer **buffer, const ReadOptions *options = NULL);
6020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
61693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huberprotected:
62693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    virtual ~MPEG4Source();
63693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber
6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
657b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex mLock;
667b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mFormat;
68693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<DataSource> mDataSource;
6920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t mTimescale;
70693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<SampleTable> mSampleTable;
7120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t mCurrentSampleIndex;
7205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t mCurrentFragmentIndex;
7305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Vector<SidxEntry> &mSegments;
7405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mFirstMoofOffset;
7505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mCurrentMoofOffset;
7605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mNextMoofOffset;
7705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t mCurrentTime;
7805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int32_t mLastParsedTrackId;
7905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int32_t mTrackId;
8020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
81ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int32_t mCryptoMode;    // passed in from extractor
82ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int32_t mDefaultIVSize; // passed in from extractor
83ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t mCryptoKey[16]; // passed in from extractor
84ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentAuxInfoType;
85ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentAuxInfoTypeParameter;
8648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    int32_t mCurrentDefaultSampleInfoSize;
87ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoCount;
88ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoAllocSize;
89ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t* mCurrentSampleInfoSizes;
90ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoOffsetCount;
91ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoOffsetsAllocSize;
92ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint64_t* mCurrentSampleInfoOffsets;
93ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
9420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mIsAVC;
956064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    size_t mNALLengthSize;
966064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
9720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mStarted;
9820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBufferGroup *mGroup;
10020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *mBuffer;
10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
103dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool mWantsNALFragments;
10420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1050024245e134467d120b40099da16c467dc365e76Andreas Huber    uint8_t *mSrcBuffer;
1060024245e134467d120b40099da16c467dc365e76Andreas Huber
1076064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    size_t parseNALSize(const uint8_t *data) const;
10805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseChunk(off64_t *offset);
10905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseTrackFragmentHeader(off64_t offset, off64_t size);
11005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseTrackFragmentRun(off64_t offset, off64_t size);
111ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    status_t parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size);
112ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    status_t parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size);
11305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
11405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    struct TrackFragmentHeaderInfo {
11505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        enum Flags {
11605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kBaseDataOffsetPresent         = 0x01,
11705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kSampleDescriptionIndexPresent = 0x02,
11805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleDurationPresent  = 0x08,
11905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleSizePresent      = 0x10,
12005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleFlagsPresent     = 0x20,
12105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDurationIsEmpty               = 0x10000,
12205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        };
12305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
12405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mTrackID;
12505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mFlags;
12605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint64_t mBaseDataOffset;
12705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mSampleDescriptionIndex;
12805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleDuration;
12905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleSize;
13005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleFlags;
13105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
13205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint64_t mDataOffset;
13305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
13405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    TrackFragmentHeaderInfo mTrackFragmentHeaderInfo;
13505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
13605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    struct Sample {
13705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t offset;
13805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size_t size;
13905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t duration;
140ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        uint8_t iv[16];
141ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Vector<size_t> clearsizes;
142ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Vector<size_t> encryptedsizes;
14305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
14405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Vector<Sample> mCurrentSamples;
1456064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
14620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source(const MPEG4Source &);
14720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source &operator=(const MPEG4Source &);
14820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
14920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This custom data source wraps an existing one and satisfies requests
15150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// falling entirely within a cached range from the cache while forwarding
15250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// all remaining requests to the wrapped datasource.
15350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This is used to cache the full sampletable metadata for a single track,
15450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// possibly wrapping multiple times to cover all tracks, i.e.
15550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// Each MPEG4DataSource caches the sampletable metadata for a single track.
15650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
15750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstruct MPEG4DataSource : public DataSource {
15850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource(const sp<DataSource> &source);
15950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
16050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual status_t initCheck() const;
161c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
162c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    virtual status_t getSize(off64_t *size);
16350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual uint32_t flags();
16450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
165c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    status_t setCachedRange(off64_t offset, size_t size);
16650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
16750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprotected:
16850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual ~MPEG4DataSource();
16950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprivate:
17150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex mLock;
17250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    sp<DataSource> mSource;
174c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t mCachedOffset;
17550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    size_t mCachedSize;
17650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    uint8_t *mCache;
17750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    void clearCache();
17950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource(const MPEG4DataSource &);
18150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource &operator=(const MPEG4DataSource &);
18250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber};
18350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source)
18550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    : mSource(source),
18650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCachedOffset(0),
18750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCachedSize(0),
18850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCache(NULL) {
18950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
19050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::~MPEG4DataSource() {
19250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    clearCache();
19350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
19450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Hubervoid MPEG4DataSource::clearCache() {
19650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (mCache) {
19750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        free(mCache);
19850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        mCache = NULL;
19950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
20050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
20150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedOffset = 0;
20250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedSize = 0;
20350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
20450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
20550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstatus_t MPEG4DataSource::initCheck() const {
20650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->initCheck();
20750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
20850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
209c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongssize_t MPEG4DataSource::readAt(off64_t offset, void *data, size_t size) {
21050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex::Autolock autoLock(mLock);
21150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
21250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (offset >= mCachedOffset
21350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            && offset + size <= mCachedOffset + mCachedSize) {
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);
9630a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t paddingsamples = (paddingus * samplerate + 500000) / 1000000;
9640a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    mLastTrack->meta->setInt32(kKeyEncoderPadding, paddingsamples);
9650a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                }
9660a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
9670a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            *offset += chunk_size;
9680a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            break;
9690a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        }
9700a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
971ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('f', 'r', 'm', 'a'):
972ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
97348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t original_fourcc;
974ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset, &original_fourcc, 4) < 4) {
975ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
976ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
977ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            original_fourcc = ntohl(original_fourcc);
978ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("read original format: %d", original_fourcc);
979ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc));
98048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t num_channels = 0;
98148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t sample_rate = 0;
98248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (AdjustChannelsAndRate(original_fourcc, &num_channels, &sample_rate)) {
98348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
98448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
98548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            }
986ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
987ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
988ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
989ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
990ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('t', 'e', 'n', 'c'):
991ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
992ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (chunk_size < 32) {
993ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
994ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
995ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
996ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // tenc box contains 1 byte version, 3 byte flags, 3 byte default algorithm id, one byte
997ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // default IV size, 16 bytes default KeyID
998ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // (ISO 23001-7)
999ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            char buf[4];
1000ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memset(buf, 0, 4);
1001ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 4, buf + 1, 3) < 3) {
1002ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1003ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1004ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t defaultAlgorithmId = ntohl(*((int32_t*)buf));
1005ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (defaultAlgorithmId > 1) {
1006ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only 0 (clear) and 1 (AES-128) are valid
1007ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1008ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1009ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1010ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memset(buf, 0, 4);
1011ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 7, buf + 3, 1) < 1) {
1012ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1013ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1014ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t defaultIVSize = ntohl(*((int32_t*)buf));
1015ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1016ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((defaultAlgorithmId == 0 && defaultIVSize != 0) ||
1017ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    (defaultAlgorithmId != 0 && defaultIVSize == 0)) {
1018ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only unencrypted data must have 0 IV size
1019ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1020ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            } else if (defaultIVSize != 0 &&
1021ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    defaultIVSize != 8 &&
1022ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    defaultIVSize != 16) {
1023ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only supported sizes are 0, 8 and 16
1024ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1025ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1026ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1027ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint8_t defaultKeyId[16];
1028ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1029ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 8, &defaultKeyId, 16) < 16) {
1030ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1031ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1032ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1033ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setInt32(kKeyCryptoMode, defaultAlgorithmId);
1034ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setInt32(kKeyCryptoDefaultIVSize, defaultIVSize);
1035ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setData(kKeyCryptoKey, 'tenc', defaultKeyId, 16);
1036ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
1037ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1038ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1039ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
104020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'k', 'h', 'd'):
104120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1042ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            status_t err;
1043ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) {
1044ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber                return err;
104520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
104620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
104720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
104820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
104920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
105020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1051ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('p', 's', 's', 'h'):
1052ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
1053ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            PsshInfo pssh;
1054ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1055ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 4, &pssh.uuid, 16) < 16) {
1056ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1057ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1058ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1059ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t psshdatalen = 0;
1060ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 20, &psshdatalen, 4) < 4) {
1061ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1062ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1063ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            pssh.datalen = ntohl(psshdatalen);
1064ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("pssh data size: %d", pssh.datalen);
1065ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (pssh.datalen + 20 > chunk_size) {
1066ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // pssh data length exceeds size of containing box
1067ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1068ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1069ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1070ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            pssh.data = new uint8_t[pssh.datalen];
1071ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("allocated pssh @ %p", pssh.data);
1072ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ssize_t requested = (ssize_t) pssh.datalen;
1073ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 24, pssh.data, requested) < requested) {
1074ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1075ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1076ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mPssh.push_back(pssh);
1077ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1078ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
1079ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1080ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1081ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
108220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'h', 'd'):
108320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
108420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
108520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
108620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
108720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
108820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t version;
108934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
109020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, &version, sizeof(version))
109120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(version)) {
109220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
109320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
109420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1095c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t timescale_offset;
109620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
109720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
109820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 16;
109920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else if (version == 0) {
110020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 8;
110120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
110220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
110320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
110420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
110520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t timescale;
110634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
110720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        timescale_offset, &timescale, sizeof(timescale))
110820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(timescale)) {
110920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
111020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
111120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
111220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->timescale = ntohl(timescale);
111320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
111405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            int64_t duration = 0;
111520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
111634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
111720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration, sizeof(duration))
111820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration)) {
111920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
112020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
112120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = ntoh64(duration);
112220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
112305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t duration32;
112434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
112520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration32, sizeof(duration32))
112620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration32)) {
112720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
112820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
112905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // ffmpeg sets duration to -1, which is incorrect.
113005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (duration32 != 0xffffffff) {
113105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    duration = ntohl(duration32);
113205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
113320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
113448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mLastTrack->meta->setInt64(
113548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                    kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
113620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11377a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            uint8_t lang[2];
11387a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            off64_t lang_offset;
11397a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            if (version == 1) {
11407a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                lang_offset = timescale_offset + 4 + 8;
11417a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            } else if (version == 0) {
11427a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                lang_offset = timescale_offset + 4 + 4;
11437a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            } else {
11447a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                return ERROR_IO;
11457a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            }
11467a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
11477a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            if (mDataSource->readAt(lang_offset, &lang, sizeof(lang))
11487a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                    < (ssize_t)sizeof(lang)) {
11497a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                return ERROR_IO;
11507a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            }
11517a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
11527a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // To get the ISO-639-2/T three character language code
11537a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // 1 bit pad followed by 3 5-bits characters. Each character
11547a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // is packed as the difference between its ASCII value and 0x60.
11557a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            char lang_code[4];
11567a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[0] = ((lang[0] >> 2) & 0x1f) + 0x60;
11577a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[1] = ((lang[0] & 0x3) << 3 | (lang[1] >> 5)) + 0x60;
11587a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[2] = (lang[1] & 0x1f) + 0x60;
11597a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[3] = '\0';
11607a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
11617a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            mLastTrack->meta->setCString(
11627a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                    kKeyMediaLanguage, lang_code);
11637a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
116420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
116520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
116620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
116720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
116820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'd'):
116920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
117020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 8) {
117120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
117220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
117320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
117420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8];
1175c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size < (off64_t)sizeof(buffer)) {
1176bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1177bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
1178bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
117934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, 8) < 8) {
118120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
118220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
118320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
118420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
118520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
118620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
118720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
118820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
118920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t entry_count = U32_AT(&buffer[4]);
119020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
119120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (entry_count > 1) {
11923b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // For 3GPP timed text, there could be multiple tx3g boxes contain
11933b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // multiple text display formats. These formats will be used to
11943b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // display the timed text.
1195ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // For encrypted files, there may also be more than one entry.
11963b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                const char *mime;
11973b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1198ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) &&
1199ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                        strcasecmp(mime, "application/octet-stream")) {
12003b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    // For now we only support a single type of media per track.
12013b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    mLastTrack->skipTrack = true;
12023b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    *offset += chunk_size;
12033b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    break;
12043b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                }
120520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1206c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
120720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + 8;
120820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            for (uint32_t i = 0; i < entry_count; ++i) {
120920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
121020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
121120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
121220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
121320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1214bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1215bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1216bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1217bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
121820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
121920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
122020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
122120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
122248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        case FOURCC('e', 'n', 'c', 'a'):
122320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
1224371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
122520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
122620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8 + 20];
122720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
122820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic AudioSampleEntry size.
122920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
123020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
123120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
123234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
123320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
123420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
123520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
123620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
123720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
123848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t num_channels = U16_AT(&buffer[16]);
123920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
124081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint16_t sample_size = U16_AT(&buffer[18]);
124181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
124281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
124348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (chunk_type != FOURCC('e', 'n', 'c', 'a')) {
124448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                // if the chunk type is enca, we'll get the type from the sinf/frma box later
124548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
124648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate);
124720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
124848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            ALOGV("*** coding='%s' %d channels, size %d, rate %d\n",
124981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                   chunk, num_channels, sample_size, sample_rate);
125020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
125120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
125220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1253c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
125420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
125520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
125620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
125720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
125820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
125920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
126020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1261bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1262bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1263bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1264bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
126520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
126620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
126720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
126820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
1269ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('e', 'n', 'c', 'v'):
127020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
1271e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('H', '2', '6', '3'):
1272e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('h', '2', '6', '3'):
127320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
127420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
12757be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber            mHasVideo = true;
12767be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
127720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[78];
127820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
127920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic VideoSampleEntry size.
128020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
128120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
128220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
128334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
128420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
128520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
128620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
128720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
128820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
128920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t width = U16_AT(&buffer[6 + 18]);
129020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t height = U16_AT(&buffer[6 + 20]);
129120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1292ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // The video sample is not standard-compliant if it has invalid dimension.
1293a6256238d9015c42129fe43791968768fe501efaJames Dong            // Use some default width and height value, and
1294a6256238d9015c42129fe43791968768fe501efaJames Dong            // let the decoder figure out the actual width and height (and thus
1295a6256238d9015c42129fe43791968768fe501efaJames Dong            // be prepared for INFO_FOMRAT_CHANGED event).
1296a6256238d9015c42129fe43791968768fe501efaJames Dong            if (width == 0)  width  = 352;
1297a6256238d9015c42129fe43791968768fe501efaJames Dong            if (height == 0) height = 288;
1298a6256238d9015c42129fe43791968768fe501efaJames Dong
1299134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            // printf("*** coding='%s' width=%d height=%d\n",
1300134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            //        chunk, width, height);
130120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1302ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (chunk_type != FOURCC('e', 'n', 'c', 'v')) {
1303ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // if the chunk type is encv, we'll get the type from the sinf/frma box later
1304ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
1305ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
130620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyWidth, width);
130720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyHeight, height);
130820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1309c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
131020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
131120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
131220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
131320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
131420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
131520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
131620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1317bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1318bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1319bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1320bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
132120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
132220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
132320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
132420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'c', 'o'):
132520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('c', 'o', '6', '4'):
132620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
132720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
132820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setChunkOffsetParams(
132920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
133020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
133120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
133220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
133320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
133420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
133520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
133620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
133720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
133820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
133920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'c'):
134020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
134120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
134220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleToChunkParams(
134320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
134420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
134520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
134620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
134720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
134820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
134920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
135020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
135120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
135220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
135320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'z'):
135420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'z', '2'):
135520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
135720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleSizeParams(
135820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
135920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
136020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
136120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
136220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
136320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1364738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            size_t max_size;
136549110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            err = mLastTrack->sampleTable->getMaxSampleSize(&max_size);
136649110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber
136749110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            if (err != OK) {
136849110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber                return err;
136949110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            }
1370738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber
137105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (max_size != 0) {
137205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // Assume that a given buffer only contains at most 10 chunks,
137305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // each chunk originally prefixed with a 2 byte length will
137405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
137505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // and thus will grow by 2 bytes per chunk.
137605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
137705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            } else {
137805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // No size was specified. Pick a conservatively large size.
137905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                int32_t width, height;
138005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (mLastTrack->meta->findInt32(kKeyWidth, &width) &&
138105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        mLastTrack->meta->findInt32(kKeyHeight, &height)) {
138205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    mLastTrack->meta->setInt32(kKeyMaxInputSize, width * height * 3 / 2);
138305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                } else {
138405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ALOGE("No width or height, assuming worst case 1080p");
138505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    mLastTrack->meta->setInt32(kKeyMaxInputSize, 3110400);
138605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
138705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
138820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
1389113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong
1390113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            // Calculate average frame rate.
1391113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            const char *mime;
1392113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1393113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            if (!strncasecmp("video/", mime, 6)) {
1394113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                size_t nSamples = mLastTrack->sampleTable->countSamples();
1395113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                int64_t durationUs;
1396113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                if (mLastTrack->meta->findInt64(kKeyDuration, &durationUs)) {
1397113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                    if (durationUs > 0) {
1398113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                        int32_t frameRate = (nSamples * 1000000LL +
1399113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                                    (durationUs >> 1)) / durationUs;
1400113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                        mLastTrack->meta->setInt32(kKeyFrameRate, frameRate);
1401113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                    }
1402113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                }
1403113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            }
1404113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong
140520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
140620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
140720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
140820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 't', 's'):
140920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
141020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
141120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setTimeToSampleParams(
141220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
141320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
141420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
141520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
141620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
141720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
141820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
141920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
142020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
142120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14224931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        case FOURCC('c', 't', 't', 's'):
14234931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        {
14244931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            status_t err =
14254931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                mLastTrack->sampleTable->setCompositionTimeToSampleParams(
14264931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                        data_offset, chunk_data_size);
14274931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
14284931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            if (err != OK) {
14294931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                return err;
14304931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            }
14314931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
14324931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            *offset += chunk_size;
14334931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            break;
14344931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        }
14354931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
143620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 's'):
143720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
143820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
143920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSyncSampleParams(
144020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
144120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
144220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
144320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
144420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
144520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
144620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
144720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
144820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
144920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14504948818cb91176df74c972ac27b2f392b5d148bcJames Dong        // @xyz
14514948818cb91176df74c972ac27b2f392b5d148bcJames Dong        case FOURCC('\xA9', 'x', 'y', 'z'):
14524948818cb91176df74c972ac27b2f392b5d148bcJames Dong        {
14534948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Best case the total data length inside "@xyz" box
14544948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // would be 8, for instance "@xyz" + "\x00\x04\x15\xc7" + "0+0/",
14554948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // where "\x00\x04" is the text string length with value = 4,
14564948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // "\0x15\xc7" is the language code = en, and "0+0" is a
14574948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // location (string) value with longitude = 0 and latitude = 0.
14584948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (chunk_data_size < 8) {
14594948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_MALFORMED;
14604948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
14614948818cb91176df74c972ac27b2f392b5d148bcJames Dong
14624948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Worst case the location string length would be 18,
14634948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // for instance +90.0000-180.0000, without the trailing "/" and
14644948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // the string length + language code.
14654948818cb91176df74c972ac27b2f392b5d148bcJames Dong            char buffer[18];
14664948818cb91176df74c972ac27b2f392b5d148bcJames Dong
14674948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Substracting 5 from the data size is because the text string length +
14684948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // language code takes 4 bytes, and the trailing slash "/" takes 1 byte.
14694948818cb91176df74c972ac27b2f392b5d148bcJames Dong            off64_t location_length = chunk_data_size - 5;
14704948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (location_length >= (off64_t) sizeof(buffer)) {
14714948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_MALFORMED;
14724948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
14734948818cb91176df74c972ac27b2f392b5d148bcJames Dong
14744948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (mDataSource->readAt(
14754948818cb91176df74c972ac27b2f392b5d148bcJames Dong                        data_offset + 4, buffer, location_length) < location_length) {
14764948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_IO;
14774948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
14784948818cb91176df74c972ac27b2f392b5d148bcJames Dong
14794948818cb91176df74c972ac27b2f392b5d148bcJames Dong            buffer[location_length] = '\0';
14804948818cb91176df74c972ac27b2f392b5d148bcJames Dong            mFileMetaData->setCString(kKeyLocation, buffer);
14814948818cb91176df74c972ac27b2f392b5d148bcJames Dong            *offset += chunk_size;
14824948818cb91176df74c972ac27b2f392b5d148bcJames Dong            break;
14834948818cb91176df74c972ac27b2f392b5d148bcJames Dong        }
14844948818cb91176df74c972ac27b2f392b5d148bcJames Dong
148520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('e', 's', 'd', 's'):
148620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
148720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
148820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
148920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
149020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
149120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[256];
1492c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size > (off64_t)sizeof(buffer)) {
149320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
149420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
149520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
149634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
149720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
149820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
149920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
150020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
150120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
150220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
150320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
150420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
150520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
150620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
150720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
150820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1509ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            if (mPath.size() >= 2
1510ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
1511ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // Information from the ESDS must be relied on for proper
1512ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // setup of sample rate and channel count for MPEG4 Audio.
1513ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // The generic header appears to only contain generic
1514ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // information...
1515ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1516ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio(
1517ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                        &buffer[4], chunk_data_size - 4);
1518ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1519ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                if (err != OK) {
1520ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    return err;
1521ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                }
1522ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            }
1523ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
152420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
152520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
152620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
152720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
152820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', 'C'):
152920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1530d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson            sp<ABuffer> buffer = new ABuffer(chunk_data_size);
153120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
153234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
1533d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson                        data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
153420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
153520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
153620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
153720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
1538d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson                    kKeyAVCC, kTypeAVCC, buffer->data(), chunk_data_size);
153920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
154020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
154120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
154220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
154320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1544244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        case FOURCC('d', '2', '6', '3'):
1545244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        {
154617e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            /*
154717e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * d263 contains a fixed 7 bytes part:
154817e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   vendor - 4 bytes
154917e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   version - 1 byte
155017e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   level - 1 byte
155117e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   profile - 1 byte
155217e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * optionally, "d263" box itself may contain a 16-byte
155317e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * bit rate box (bitr)
155417e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   average bit rate - 4 bytes
155517e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   max bit rate - 4 bytes
155617e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             */
155717e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            char buffer[23];
155817e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            if (chunk_data_size != 7 &&
155917e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong                chunk_data_size != 23) {
156029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Incorrect D263 box size %lld", chunk_data_size);
1561244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                return ERROR_MALFORMED;
1562244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            }
1563244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1564244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            if (mDataSource->readAt(
1565244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                    data_offset, buffer, chunk_data_size) < chunk_data_size) {
1566244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                return ERROR_IO;
1567244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            }
1568244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1569244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size);
1570244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1571244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            *offset += chunk_size;
1572244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            break;
1573244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        }
1574244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
157572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'e', 't', 'a'):
157672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
157772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            uint8_t buffer[4];
1578c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size < (off64_t)sizeof(buffer)) {
1579bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1580bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
1581bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
158272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
158372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, buffer, 4) < 4) {
158472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
158572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
158672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
158772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (U32_AT(buffer) != 0) {
158872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                // Should be version 0, flags 0.
1589ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
1590ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // If it's not, let's assume this is one of those
1591ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // apparently malformed chunks that don't have flags
1592ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // and completely different semantics than what's
1593ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // in the MPEG4 specs and skip it.
1594ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                *offset += chunk_size;
1595ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                return OK;
159672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
159772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1598c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
159972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset = data_offset + sizeof(buffer);
160072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            while (*offset < stop_offset) {
160172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                status_t err = parseChunk(offset, depth + 1);
160272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
160372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
160472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
160572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
1606bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1607bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1608bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1609bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
161072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
161172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
161272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
16135d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('m', 'e', 'a', 'n'):
16145d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('n', 'a', 'm', 'e'):
161572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('d', 'a', 't', 'a'):
161672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
161772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mPath.size() == 6 && underMetaDataPath(mPath)) {
161872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                status_t err = parseMetaData(data_offset, chunk_data_size);
161972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
162072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
162172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
162272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
162372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
162472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
162572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset += chunk_size;
162672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
162772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
162872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
162972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'v', 'h', 'd'):
163072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
1631fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            if (chunk_data_size < 24) {
163272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_MALFORMED;
163372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
163472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1635fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            uint8_t header[24];
163672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
163772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, header, sizeof(header))
163872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    < (ssize_t)sizeof(header)) {
163972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
164072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
164172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1642fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            uint64_t creationTime;
164372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (header[0] == 1) {
164472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U64_AT(&header[4]);
1645fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                mHeaderTimescale = U32_AT(&header[20]);
1646bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (header[0] != 0) {
1647bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
164872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            } else {
164972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U32_AT(&header[4]);
1650fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                mHeaderTimescale = U32_AT(&header[12]);
165172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
165272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
165372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            String8 s;
165472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            convertTimeToDate(creationTime, &s);
165572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
165672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(kKeyDate, s.string());
165772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
165872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset += chunk_size;
165972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
166072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
166172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1662dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        case FOURCC('m', 'd', 'a', 't'):
1663dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        {
1664ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("mdat chunk, drm: %d", mIsDrm);
1665dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (!mIsDrm) {
1666dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                *offset += chunk_size;
1667dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                break;
1668dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
1669dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
1670dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (chunk_size < 8) {
1671dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
1672dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
1673dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
1674dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return parseDrmSINF(offset, data_offset);
1675dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
1676dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
16773b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        case FOURCC('h', 'd', 'l', 'r'):
16783b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        {
16793b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t buffer;
16803b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (mDataSource->readAt(
16813b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                        data_offset + 8, &buffer, 4) < 4) {
16823b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_IO;
16833b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
16843b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
16853b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type = ntohl(buffer);
16863b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            // For the 3GPP file format, the handler-type within the 'hdlr' box
1687e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            // shall be 'text'. We also want to support 'sbtl' handler type
1688e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            // for a practical reason as various MPEG4 containers use it.
1689e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            if (type == FOURCC('t', 'e', 'x', 't') || type == FOURCC('s', 'b', 't', 'l')) {
16903b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
16913b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
16923b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
16933b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            *offset += chunk_size;
16943b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            break;
16953b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        }
16963b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
16977a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        case FOURCC('t', 'x', '3', 'g'):
16987a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        {
16993b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type;
17003b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            const void *data;
17013b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            size_t size = 0;
17023b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (!mLastTrack->meta->findData(
17033b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    kKeyTextFormatData, &type, &data, &size)) {
17043b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                size = 0;
17053b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17063b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17073b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint8_t *buffer = new uint8_t[size + chunk_size];
17083b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17093b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (size > 0) {
17103b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                memcpy(buffer, data, size);
17113b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17123b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17133b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size))
17143b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    < chunk_size) {
17153b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                delete[] buffer;
17163b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                buffer = NULL;
17173b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17183b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_IO;
17193b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17203b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17213b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            mLastTrack->meta->setData(
17223b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    kKeyTextFormatData, 0, buffer, size + chunk_size);
17233b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17243b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            delete[] buffer;
17257a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
17267a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            *offset += chunk_size;
17277a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            break;
17287a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        }
17297a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
1730515e855eae78aa495da58356486aaa666cb57fd1James Dong        case FOURCC('c', 'o', 'v', 'r'):
1731515e855eae78aa495da58356486aaa666cb57fd1James Dong        {
1732515e855eae78aa495da58356486aaa666cb57fd1James Dong            if (mFileMetaData != NULL) {
17333856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("chunk_data_size = %lld and data_offset = %lld",
1734515e855eae78aa495da58356486aaa666cb57fd1James Dong                        chunk_data_size, data_offset);
17351552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1);
1736515e855eae78aa495da58356486aaa666cb57fd1James Dong                if (mDataSource->readAt(
17371552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                    data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) {
1738515e855eae78aa495da58356486aaa666cb57fd1James Dong                    return ERROR_IO;
1739515e855eae78aa495da58356486aaa666cb57fd1James Dong                }
1740515e855eae78aa495da58356486aaa666cb57fd1James Dong                const int kSkipBytesOfDataBox = 16;
1741515e855eae78aa495da58356486aaa666cb57fd1James Dong                mFileMetaData->setData(
1742515e855eae78aa495da58356486aaa666cb57fd1James Dong                    kKeyAlbumArt, MetaData::TYPE_NONE,
17431552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                    buffer->data() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox);
1744515e855eae78aa495da58356486aaa666cb57fd1James Dong            }
1745515e855eae78aa495da58356486aaa666cb57fd1James Dong
1746515e855eae78aa495da58356486aaa666cb57fd1James Dong            *offset += chunk_size;
1747515e855eae78aa495da58356486aaa666cb57fd1James Dong            break;
1748515e855eae78aa495da58356486aaa666cb57fd1James Dong        }
1749515e855eae78aa495da58356486aaa666cb57fd1James Dong
17505d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('-', '-', '-', '-'):
17515d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        {
17525d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentMean.clear();
17535d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentName.clear();
17545d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentData.clear();
17555d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            *offset += chunk_size;
17565d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            break;
17575d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        }
17585d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen
175905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('s', 'i', 'd', 'x'):
176005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        {
176105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            parseSegmentIndex(data_offset, chunk_data_size);
176205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset += chunk_size;
176305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return UNKNOWN_ERROR; // stop parsing after sidx
176405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
176505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
176620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
176720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
176820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
176920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
177020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
177120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
177220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
177320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
177420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
177520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
177605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) {
177705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen  ALOGV("MPEG4Extractor::parseSegmentIndex");
177805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
177905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 12) {
178005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      return -EINVAL;
178105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
178205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
178305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
178405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) {
178505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
178605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
178705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
178805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t version = flags >> 24;
178905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    flags &= 0xffffff;
179005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
179105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx version %d", version);
179205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
179305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t referenceId;
179405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, &referenceId)) {
179505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
179605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
179705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
179805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t timeScale;
179905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 8, &timeScale)) {
180005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
180105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
180205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx refid/timescale: %d/%d", referenceId, timeScale);
180305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
180405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t earliestPresentationTime;
180505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t firstOffset;
180605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
180705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 12;
180805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 12;
180905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
181005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (version == 0) {
181105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 8) {
181205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
181305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
181405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t tmp;
181505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
181605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
181705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
181805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        earliestPresentationTime = tmp;
181905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset + 4, &tmp)) {
182005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
182105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
182205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        firstOffset = tmp;
182305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 8;
182405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 8;
182505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
182605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 16) {
182705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
182805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
182905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset, &earliestPresentationTime)) {
183005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
183105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
183205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset + 8, &firstOffset)) {
183305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
183405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
183505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 16;
183605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 16;
183705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
183805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx pres/off: %Ld/%Ld", earliestPresentationTime, firstOffset);
183905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
184005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 4) {
184105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
184205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
184305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
184405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint16_t referenceCount;
184505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt16(offset + 2, &referenceCount)) {
184605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
184705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
184805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 4;
184905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 4;
185005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("refcount: %d", referenceCount);
185105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
185205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < referenceCount * 12) {
185305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
185405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
185505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
185605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t total_duration = 0;
185705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    for (unsigned int i = 0; i < referenceCount; i++) {
185805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t d1, d2, d3;
185905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
186005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &d1) ||     // size
186105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            !mDataSource->getUInt32(offset + 4, &d2) || // duration
186205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            !mDataSource->getUInt32(offset + 8, &d3)) { // flags
186305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
186405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
186505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
186605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (d1 & 0x80000000) {
186705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGW("sub-sidx boxes not supported yet");
186805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
186905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool sap = d3 & 0x80000000;
187005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool saptype = d3 >> 28;
187105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!sap || saptype > 2) {
187205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGW("not a stream access point, or unsupported type");
187305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
187405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        total_duration += d2;
187505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 12;
187605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV(" item %d, %08x %08x %08x", i, d1, d2, d3);
187705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        SidxEntry se;
187805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        se.mSize = d1 & 0x7fffffff;
187905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        se.mDurationUs = 1000000LL * d2 / timeScale;
188005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mSidxEntries.add(se);
188105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
188205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
188305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mSidxDuration = total_duration * 1000000 / timeScale;
188405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("duration: %lld", mSidxDuration);
188505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
188605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t metaDuration;
188705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mLastTrack->meta->findInt64(kKeyDuration, &metaDuration) || metaDuration == 0) {
188805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mLastTrack->meta->setInt64(kKeyDuration, mSidxDuration);
188905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
189005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
189105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
189205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
189305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
189405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
1895ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huberstatus_t MPEG4Extractor::parseTrackHeader(
1896c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t data_offset, off64_t data_size) {
1897ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (data_size < 4) {
1898ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_MALFORMED;
1899ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1900ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1901ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint8_t version;
1902ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (mDataSource->readAt(data_offset, &version, 1) < 1) {
1903ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_IO;
1904ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1905ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1906ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    size_t dynSize = (version == 1) ? 36 : 24;
1907ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1908ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint8_t buffer[36 + 60];
1909ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1910c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    if (data_size != (off64_t)dynSize + 60) {
1911ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_MALFORMED;
1912ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1913ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1914ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (mDataSource->readAt(
1915ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber                data_offset, buffer, data_size) < (ssize_t)data_size) {
1916ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_IO;
1917ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1918ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1919ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint64_t ctime, mtime, duration;
1920ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t id;
1921ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1922ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (version == 1) {
1923ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        ctime = U64_AT(&buffer[4]);
1924ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mtime = U64_AT(&buffer[12]);
1925ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        id = U32_AT(&buffer[20]);
1926ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        duration = U64_AT(&buffer[28]);
192704022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen    } else if (version == 0) {
1928ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        ctime = U32_AT(&buffer[4]);
1929ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mtime = U32_AT(&buffer[8]);
1930ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        id = U32_AT(&buffer[12]);
1931ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        duration = U32_AT(&buffer[20]);
193204022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen    } else {
193304022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen        return ERROR_UNSUPPORTED;
1934ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1935ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1936ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    mLastTrack->meta->setInt32(kKeyTrackID, id);
1937ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1938ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    size_t matrixOffset = dynSize + 16;
1939ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a00 = U32_AT(&buffer[matrixOffset]);
1940ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a01 = U32_AT(&buffer[matrixOffset + 4]);
1941ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t dx = U32_AT(&buffer[matrixOffset + 8]);
1942ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a10 = U32_AT(&buffer[matrixOffset + 12]);
1943ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a11 = U32_AT(&buffer[matrixOffset + 16]);
1944ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t dy = U32_AT(&buffer[matrixOffset + 20]);
1945ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1946ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#if 0
1947df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("x' = %.2f * x + %.2f * y + %.2f",
1948ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber         a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f);
1949df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("y' = %.2f * x + %.2f * y + %.2f",
1950ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber         a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f);
1951ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#endif
1952ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1953ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t rotationDegrees;
1954ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1955ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    static const int32_t kFixedOne = 0x10000;
1956ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) {
1957ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        // Identity, no rotation
1958ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 0;
1959ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) {
1960ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 90;
1961ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) {
1962ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 270;
1963ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) {
1964ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 180;
1965ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else {
19665ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("We only support 0,90,180,270 degree rotation matrices");
1967ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 0;
1968ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1969ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1970ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (rotationDegrees != 0) {
1971ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees);
1972ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1973ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1974b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    // Handle presentation display size, which could be different
1975b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    // from the image size indicated by kKeyWidth and kKeyHeight.
1976ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t width = U32_AT(&buffer[dynSize + 52]);
1977ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t height = U32_AT(&buffer[dynSize + 56]);
1978b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    mLastTrack->meta->setInt32(kKeyDisplayWidth, width >> 16);
1979b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    mLastTrack->meta->setInt32(kKeyDisplayHeight, height >> 16);
1980ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1981ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    return OK;
1982ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber}
1983ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1984c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseMetaData(off64_t offset, size_t size) {
198572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (size < 4) {
198672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_MALFORMED;
198772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
198872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
198972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint8_t *buffer = new uint8_t[size + 1];
199072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (mDataSource->readAt(
199172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                offset, buffer, size) != (ssize_t)size) {
199272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        delete[] buffer;
199372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        buffer = NULL;
199472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
199572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_IO;
199672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
199772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
199872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t flags = U32_AT(buffer);
199972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
200072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t metadataKey = 0;
20015d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    char chunk[5];
20025d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    MakeFourCCString(mPath[4], chunk);
20035d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    ALOGV("meta: %s @ %lld", chunk, offset);
200472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    switch (mPath[4]) {
200572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'a', 'l', 'b'):
200672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
200772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbum;
200872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
200972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
201072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'A', 'R', 'T'):
201172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
201272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyArtist;
201372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
201472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
201566ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        case FOURCC('a', 'A', 'R', 'T'):
201666ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        {
201766ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            metadataKey = kKeyAlbumArtist;
201866ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            break;
201966ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        }
202072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'd', 'a', 'y'):
202172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
202272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyYear;
202372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
202472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
202572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'n', 'a', 'm'):
202672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
202772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyTitle;
202872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
202972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
203072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'w', 'r', 't'):
203172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
203272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyWriter;
203372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
203472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
203572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('c', 'o', 'v', 'r'):
203672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
203772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbumArt;
203872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
203972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
204072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('g', 'n', 'r', 'e'):
204172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
204272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyGenre;
204372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
204472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
204526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC(0xa9, 'g', 'e', 'n'):
204626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
204726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            metadataKey = kKeyGenre;
204826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
204926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
205011f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        case FOURCC('c', 'p', 'i', 'l'):
205111f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        {
205211f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            if (size == 9 && flags == 21) {
205311f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                char tmp[16];
205411f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                sprintf(tmp, "%d",
205511f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                        (int)buffer[size - 1]);
205611f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen
205711f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                mFileMetaData->setCString(kKeyCompilation, tmp);
205811f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            }
205911f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            break;
206011f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        }
206172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('t', 'r', 'k', 'n'):
206272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
206372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (size == 16 && flags == 0) {
206472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char tmp[16];
2065afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTrack = (uint16_t*)&buffer[10];
2066afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTotalTracks = (uint16_t*)&buffer[12];
2067afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                sprintf(tmp, "%d/%d", ntohs(*pTrack), ntohs(*pTotalTracks));
206872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
206972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
207072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
207172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
207272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
207326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC('d', 'i', 's', 'k'):
207426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
2075afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik            if ((size == 14 || size == 16) && flags == 0) {
207626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                char tmp[16];
2077afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pDisc = (uint16_t*)&buffer[10];
2078afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTotalDiscs = (uint16_t*)&buffer[12];
2079afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                sprintf(tmp, "%d/%d", ntohs(*pDisc), ntohs(*pTotalDiscs));
208026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
208126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(kKeyDiscNumber, tmp);
208226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            }
208326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
208426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
20855d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('-', '-', '-', '-'):
20865d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        {
20875d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            buffer[size] = '\0';
20885d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            switch (mPath[5]) {
20895d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('m', 'e', 'a', 'n'):
20905d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentMean.setTo((const char *)buffer + 4);
20915d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
20925d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('n', 'a', 'm', 'e'):
20935d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentName.setTo((const char *)buffer + 4);
20945d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
20955d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('d', 'a', 't', 'a'):
20965d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentData.setTo((const char *)buffer + 8);
20975d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
20985d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            }
20998c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
21008c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // Once we have a set of mean/name/data info, go ahead and process
21018c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // it to see if its something we are interested in.  Whether or not
21028c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // were are interested in the specific tag, make sure to clear out
21038c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // the set so we can be ready to process another tuple should one
21048c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // show up later in the file.
21058c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            if ((mLastCommentMean.length() != 0) &&
21068c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                (mLastCommentName.length() != 0) &&
21078c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                (mLastCommentData.length() != 0)) {
21088c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
21098c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                if (mLastCommentMean == "com.apple.iTunes"
21108c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        && mLastCommentName == "iTunSMPB") {
21118c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    int32_t delay, padding;
21128c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    if (sscanf(mLastCommentData,
21138c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                               " %*x %x %x %*x", &delay, &padding) == 2) {
21148c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
21158c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        mLastTrack->meta->setInt32(kKeyEncoderPadding, padding);
21168c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    }
21175d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                }
21188c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
21195d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentMean.clear();
21205d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentName.clear();
21215d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentData.clear();
21225d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            }
21235d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            break;
21245d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        }
212526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
212672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        default:
212772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
212872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
212972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
213072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (size >= 8 && metadataKey) {
213172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        if (metadataKey == kKeyAlbumArt) {
213272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setData(
213372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    kKeyAlbumArt, MetaData::TYPE_NONE,
213472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    buffer + 8, size - 8);
213572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else if (metadataKey == kKeyGenre) {
213672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (flags == 0) {
213726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // uint8_t genre code, iTunes genre codes are
213826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // the standard id3 codes, except they start
213926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // at 1 instead of 0 (e.g. Pop is 14, not 13)
214026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // We use standard id3 numbering, so subtract 1.
214126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                int genrecode = (int)buffer[size - 1];
214226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                genrecode--;
214326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                if (genrecode < 0) {
214426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                    genrecode = 255; // reserved for 'unknown genre'
214526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                }
214672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char genre[10];
214726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                sprintf(genre, "%d", genrecode);
214872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
214972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(metadataKey, genre);
215026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            } else if (flags == 1) {
215126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // custom genre string
215226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                buffer[size] = '\0';
215326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
215426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(
215526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                        metadataKey, (const char *)buffer + 8);
215672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
215772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else {
215872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            buffer[size] = '\0';
215972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
216072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(
216172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    metadataKey, (const char *)buffer + 8);
216272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
216372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
216472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
216572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    delete[] buffer;
216672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    buffer = NULL;
216772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
216872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return OK;
216972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
217072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
2171693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
217220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
217320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
2174693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return NULL;
217520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
217620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
217720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
217820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
217920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
2180693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber            return NULL;
218120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
218220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
218320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
218420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
218520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
218620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2187371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
2188371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
2189371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
2190371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
2191ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("getTrack called, pssh: %d", mPssh.size());
2192ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2193693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    return new MPEG4Source(
219405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            track->meta, mDataSource, track->timescale, track->sampleTable,
219505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mSidxEntries, mMoofOffset);
219620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
219720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2198bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber// static
2199bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) {
2200bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const char *mime;
2201bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    CHECK(track->meta->findCString(kKeyMIMEType, &mime));
2202bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2203bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    uint32_t type;
2204bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const void *data;
2205bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    size_t size;
2206bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
2207bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyAVCC, &type, &data, &size)
2208bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeAVCC) {
2209bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
2210bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
2211bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
2212bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
2213bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyESDS, &type, &data, &size)
2214bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeESDS) {
2215bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
2216bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
2217bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    }
2218bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2219169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber    if (!track->sampleTable->isValid()) {
2220169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        // Make sure we have all the metadata we need.
2221169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        return ERROR_MALFORMED;
2222169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber    }
2223169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber
2224bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    return OK;
2225bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber}
2226bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2227ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
2228ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        const void *esds_data, size_t esds_size) {
2229ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    ESDS esds(esds_data, esds_size);
223081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
223181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    uint8_t objectTypeIndication;
223281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
223381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return ERROR_MALFORMED;
223481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
223581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
223681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (objectTypeIndication == 0xe1) {
223781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        // This isn't MPEG4 audio at all, it's QCELP 14k...
223881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
223981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return OK;
224081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
224181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
2242633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong    if (objectTypeIndication  == 0x6b) {
2243633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // The media subtype is MP3 audio
2244633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // Our software MP3 audio decoder may not be able to handle
2245633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // packetized MP3 audio; for now, lets just return ERROR_UNSUPPORTED
224629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("MP3 track in MP4/3GPP file is not supported");
2247633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        return ERROR_UNSUPPORTED;
2248633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong    }
2249633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong
2250ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    const uint8_t *csd;
2251ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    size_t csd_size;
2252ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (esds.getCodecSpecificInfo(
2253ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                (const void **)&csd, &csd_size) != OK) {
2254ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
2255ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2256ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2257ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#if 0
2258ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    printf("ESD of size %d\n", csd_size);
2259ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    hexdump(csd, csd_size);
2260ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#endif
2261ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2262a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    if (csd_size == 0) {
2263a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // There's no further information, i.e. no codec specific data
2264a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // Let's assume that the information provided in the mpeg4 headers
2265a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // is accurate and hope for the best.
2266a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
2267a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        return OK;
2268a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    }
2269a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
2270ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (csd_size < 2) {
2271ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
2272ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2273ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2274aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    ABitReader br(csd, csd_size);
2275aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    uint32_t objectType = br.getBits(5);
2276ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2277aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    if (objectType == 31) {  // AAC-ELD => additional 6 bits
2278aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        objectType = 32 + br.getBits(6);
2279ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2280ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2281aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    uint32_t freqIndex = br.getBits(4);
2282aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
2283ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t sampleRate = 0;
2284ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t numChannels = 0;
2285ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (freqIndex == 15) {
2286ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        if (csd_size < 5) {
2287ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            return ERROR_MALFORMED;
2288ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
2289aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        sampleRate = br.getBits(24);
2290aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        numChannels = br.getBits(4);
2291ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    } else {
2292595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen        numChannels = br.getBits(4);
2293595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen        if (objectType == 5) {
2294595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen            // SBR specific config per 14496-3 table 1.13
2295595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen            freqIndex = br.getBits(4);
2296595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen            if (freqIndex == 15) {
2297595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen                if (csd_size < 8) {
2298595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen                    return ERROR_MALFORMED;
2299595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen                }
2300595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen                sampleRate = br.getBits(24);
2301595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen            }
2302ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
2303ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2304595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen        if (sampleRate == 0) {
2305595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen            static uint32_t kSamplingRate[] = {
2306595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen                96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
2307595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen                16000, 12000, 11025, 8000, 7350
2308595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen            };
2309595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen
2310595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen            if (freqIndex == 13 || freqIndex == 14) {
2311595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen                return ERROR_MALFORMED;
2312595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen            }
2313595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen
2314595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen            sampleRate = kSamplingRate[freqIndex];
2315595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen        }
2316ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2317ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2318ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (numChannels == 0) {
2319ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_UNSUPPORTED;
2320ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2321ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2322ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevSampleRate;
2323ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
2324ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2325ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevSampleRate != sampleRate) {
23263856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("mpeg4 audio sample rate different from previous setting. "
2327ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevSampleRate, sampleRate);
2328ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2329ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2330ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
2331ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2332ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevChannelCount;
2333ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
2334ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2335ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevChannelCount != numChannels) {
23363856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("mpeg4 audio channel count different from previous setting. "
2337ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevChannelCount, numChannels);
2338ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2339ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2340ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
2341ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2342ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    return OK;
2343ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber}
2344ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
234520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
234620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
234720111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::MPEG4Source(
234820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        const sp<MetaData> &format,
2349693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &dataSource,
235048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        int32_t timeScale,
235105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const sp<SampleTable> &sampleTable,
235205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        Vector<SidxEntry> &sidx,
235305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t firstMoofOffset)
235420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mFormat(format),
235520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDataSource(dataSource),
235648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber      mTimescale(timeScale),
235720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSampleTable(sampleTable),
235820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCurrentSampleIndex(0),
235905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentFragmentIndex(0),
236005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mSegments(sidx),
236105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mFirstMoofOffset(firstMoofOffset),
236205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentMoofOffset(firstMoofOffset),
236305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentTime(0),
2364ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoAllocSize(0),
2365ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoSizes(NULL),
2366ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoOffsetsAllocSize(0),
2367ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoOffsets(NULL),
236820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mIsAVC(false),
23696064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber      mNALLengthSize(0),
237020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mStarted(false),
237120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mGroup(NULL),
237220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mBuffer(NULL),
2373dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber      mWantsNALFragments(false),
23740024245e134467d120b40099da16c467dc365e76Andreas Huber      mSrcBuffer(NULL) {
2375ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2376ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mFormat->findInt32(kKeyCryptoMode, &mCryptoMode);
237748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    mDefaultIVSize = 0;
2378ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mFormat->findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize);
2379ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t keytype;
2380ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    const void *key;
2381ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    size_t keysize;
2382ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mFormat->findData(kKeyCryptoKey, &keytype, &key, &keysize)) {
2383ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        CHECK(keysize <= 16);
2384ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memset(mCryptoKey, 0, 16);
2385ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memcpy(mCryptoKey, key, keysize);
2386ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2387ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
238820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
238920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mFormat->findCString(kKeyMIMEType, &mime);
2390dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(success);
239120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
239218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber    mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
23936064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
23946064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    if (mIsAVC) {
23956064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        uint32_t type;
23966064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const void *data;
23976064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t size;
23986064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(format->findData(kKeyAVCC, &type, &data, &size));
23996064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
24006064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const uint8_t *ptr = (const uint8_t *)data;
24016064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
24026064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(size >= 7);
2403ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
24046064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
24056064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        // The number of bytes used to encode the length of a NAL unit.
24066064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        mNALLengthSize = 1 + (ptr[4] & 3);
24076064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
240805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
240905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    CHECK(format->findInt32(kKeyTrackID, &mTrackId));
241005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
241105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mFirstMoofOffset != 0) {
241205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t offset = mFirstMoofOffset;
241305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        parseChunk(&offset);
241405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
241520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
241620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
241720111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::~MPEG4Source() {
241820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mStarted) {
241920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        stop();
242020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
2421ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    free(mCurrentSampleInfoSizes);
2422ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    free(mCurrentSampleInfoOffsets);
242320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
242420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
242520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::start(MetaData *params) {
24267b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
24277b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
2428dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(!mStarted);
242920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
243020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t val;
2431dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (params && params->findInt32(kKeyWantsNALFragments, &val)
243220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        && val != 0) {
2433dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = true;
243420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    } else {
2435dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = false;
243620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
243720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
243820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = new MediaBufferGroup;
243920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2440738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    int32_t max_size;
2441738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
244220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2443738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    mGroup->add_buffer(new MediaBuffer(max_size));
24440024245e134467d120b40099da16c467dc365e76Andreas Huber
24450024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = new uint8_t[max_size];
244620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
244720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = true;
244820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
244920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
245020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
245120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
245220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::stop() {
24537b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
24547b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
2455dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
245620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
245720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mBuffer != NULL) {
245820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->release();
245920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
246020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
246120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24620024245e134467d120b40099da16c467dc365e76Andreas Huber    delete[] mSrcBuffer;
24630024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = NULL;
24640024245e134467d120b40099da16c467dc365e76Andreas Huber
246520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    delete mGroup;
246620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = NULL;
246720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
246820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = false;
246920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mCurrentSampleIndex = 0;
247020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
247120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
247220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
247320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
247405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseChunk(off64_t *offset) {
247505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t hdr[2];
247605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
247705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_IO;
247805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
247905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t chunk_size = ntohl(hdr[0]);
248005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t chunk_type = ntohl(hdr[1]);
248105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t data_offset = *offset + 8;
248205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
248305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (chunk_size == 1) {
248405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
248505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_IO;
248605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
248705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        chunk_size = ntoh64(chunk_size);
248805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        data_offset += 8;
248905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
249005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (chunk_size < 16) {
249105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            // The smallest valid chunk is 16 bytes long in this case.
249205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
249305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
249405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (chunk_size < 8) {
249505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // The smallest valid chunk is 8 bytes long.
249605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
249705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
249805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
249905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    char chunk[5];
250005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    MakeFourCCString(chunk_type, chunk);
250105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Source chunk %s @ %llx", chunk, *offset);
250205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
250305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t chunk_data_size = *offset + chunk_size - data_offset;
250405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
250505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    switch(chunk_type) {
250605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
250705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'r', 'a', 'f'):
250805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('m', 'o', 'o', 'f'): {
250905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t stop_offset = *offset + chunk_size;
251005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset = data_offset;
251105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            while (*offset < stop_offset) {
251205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err = parseChunk(offset);
251305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (err != OK) {
251405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return err;
251505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
251605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
251705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
2518ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // *offset points to the mdat box following this moof
251905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                parseChunk(offset); // doesn't actually parse it, just updates offset
252005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mNextMoofOffset = *offset;
252105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
252205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
252305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
252405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
252505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'f', 'h', 'd'): {
252605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err;
252705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if ((err = parseTrackFragmentHeader(data_offset, chunk_data_size)) != OK) {
252805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return err;
252905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
253005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                *offset += chunk_size;
253105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                break;
253205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
253305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
253405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'r', 'u', 'n'): {
253505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err;
253605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (mLastParsedTrackId == mTrackId) {
253705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    if ((err = parseTrackFragmentRun(data_offset, chunk_data_size)) != OK) {
253805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        return err;
253905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    }
254005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
254105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
254205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                *offset += chunk_size;
254305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                break;
254405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
254505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2546ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'a', 'i', 'z'): {
2547ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            status_t err;
2548ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((err = parseSampleAuxiliaryInformationSizes(data_offset, chunk_data_size)) != OK) {
2549ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return err;
2550ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
2551ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
2552ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
2553ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2554ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'a', 'i', 'o'): {
2555ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            status_t err;
2556ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((err = parseSampleAuxiliaryInformationOffsets(data_offset, chunk_data_size)) != OK) {
2557ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return err;
2558ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
2559ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
2560ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
2561ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2562ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2563ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('m', 'd', 'a', 't'): {
2564ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // parse DRM info if present
2565ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("MPEG4Source::parseChunk mdat");
2566ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // if saiz/saoi was previously observed, do something with the sampleinfos
2567ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
2568ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
2569ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2570ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
257105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        default: {
257205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset += chunk_size;
257305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
257405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
257505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
257605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
257705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
257805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2579ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissenstatus_t MPEG4Source::parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size) {
2580ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("parseSampleAuxiliaryInformationSizes");
2581ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // 14496-12 8.7.12
2582ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t version;
2583ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(
2584ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset, &version, sizeof(version))
2585ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            < (ssize_t)sizeof(version)) {
2586ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
2587ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2588ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2589ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (version != 0) {
2590ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_UNSUPPORTED;
2591ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2592ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
2593ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2594ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t flags;
2595ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt24(offset, &flags)) {
2596ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
2597ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2598ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 3;
2599ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2600ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (flags & 1) {
2601ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        uint32_t tmp;
2602ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
2603ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_MALFORMED;
2604ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2605ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentAuxInfoType = tmp;
2606ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        offset += 4;
2607ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
2608ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_MALFORMED;
2609ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2610ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentAuxInfoTypeParameter = tmp;
2611ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        offset += 4;
2612ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2613ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2614ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t defsize;
2615ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(offset, &defsize, 1) != 1) {
2616ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_MALFORMED;
2617ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2618ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mCurrentDefaultSampleInfoSize = defsize;
2619ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
2620ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2621ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t smplcnt;
2622ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &smplcnt)) {
2623ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_MALFORMED;
2624ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
262548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    mCurrentSampleInfoCount = smplcnt;
2626ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 4;
2627ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
262848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (mCurrentDefaultSampleInfoSize != 0) {
262948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        ALOGV("@@@@ using default sample info size of %d", mCurrentDefaultSampleInfoSize);
263048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return OK;
263148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
2632ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (smplcnt > mCurrentSampleInfoAllocSize) {
2633ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoSizes = (uint8_t*) realloc(mCurrentSampleInfoSizes, smplcnt);
2634ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoAllocSize = smplcnt;
2635ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2636ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2637ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mDataSource->readAt(offset, mCurrentSampleInfoSizes, smplcnt);
2638ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    return OK;
2639ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen}
2640ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2641ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissenstatus_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size) {
2642ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("parseSampleAuxiliaryInformationOffsets");
2643ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // 14496-12 8.7.13
2644ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t version;
2645ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(offset, &version, sizeof(version)) != 1) {
2646ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
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    uint32_t entrycount;
2657ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &entrycount)) {
2658ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
2659ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2660ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 4;
2661ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2662ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (entrycount > mCurrentSampleInfoOffsetsAllocSize) {
2663ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoOffsets = (uint64_t*) realloc(mCurrentSampleInfoOffsets, entrycount * 8);
2664ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoOffsetsAllocSize = entrycount;
2665ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2666ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mCurrentSampleInfoOffsetCount = entrycount;
2667ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2668ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < entrycount; i++) {
2669ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (version == 0) {
2670ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t tmp;
2671ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (!mDataSource->getUInt32(offset, &tmp)) {
2672ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
2673ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
2674ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mCurrentSampleInfoOffsets[i] = tmp;
2675ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset += 4;
2676ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        } else {
2677ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint64_t tmp;
2678ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (!mDataSource->getUInt64(offset, &tmp)) {
2679ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
2680ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
2681ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mCurrentSampleInfoOffsets[i] = tmp;
2682ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset += 8;
2683ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2684ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2685ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2686ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // parse clear/encrypted data
2687ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2688ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    off64_t drmoffset = mCurrentSampleInfoOffsets[0]; // from moof
2689ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2690ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    drmoffset += mCurrentMoofOffset;
2691ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int ivlength;
2692ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    CHECK(mFormat->findInt32(kKeyCryptoDefaultIVSize, &ivlength));
269348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
269448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    // read CencSampleAuxiliaryDataFormats
2695ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mCurrentSampleInfoCount; i++) {
2696ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Sample *smpl = &mCurrentSamples.editItemAt(i);
2697ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2698ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memset(smpl->iv, 0, 16);
2699ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (mDataSource->readAt(drmoffset, smpl->iv, ivlength) != ivlength) {
2700ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_IO;
2701ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2702ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2703ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        drmoffset += ivlength;
2704ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
270548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        int32_t smplinfosize = mCurrentDefaultSampleInfoSize;
270648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        if (smplinfosize == 0) {
270748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smplinfosize = mCurrentSampleInfoSizes[i];
2708ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
270948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        if (smplinfosize > ivlength) {
271048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint16_t numsubsamples;
271148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (!mDataSource->getUInt16(drmoffset, &numsubsamples)) {
2712ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
2713ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
2714ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            drmoffset += 2;
271548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            for (size_t j = 0; j < numsubsamples; j++) {
271648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                uint16_t numclear;
271748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                uint32_t numencrypted;
271848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                if (!mDataSource->getUInt16(drmoffset, &numclear)) {
271948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                    return ERROR_IO;
272048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                }
272148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                drmoffset += 2;
272248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                if (!mDataSource->getUInt32(drmoffset, &numencrypted)) {
272348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                    return ERROR_IO;
272448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                }
272548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                drmoffset += 4;
272648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->clearsizes.add(numclear);
272748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->encryptedsizes.add(numencrypted);
2728ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
272948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        } else {
273048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smpl->clearsizes.add(0);
273148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smpl->encryptedsizes.add(smpl->size);
2732ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2733ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2734ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2735ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2736ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    return OK;
2737ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen}
2738ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
273905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentHeader(off64_t offset, off64_t size) {
274005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
274105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 8) {
274205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
274305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
274405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
274505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
2746ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags
274705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
274805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
274905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
275005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & 0xff000000) {
275105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
275205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
275305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
275405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, (uint32_t*)&mLastParsedTrackId)) {
275505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
275605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
275705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
275805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mLastParsedTrackId != mTrackId) {
275905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // this is not the right track, skip it
276005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
276105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
276205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
276305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mFlags = flags;
276405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mTrackID = mLastParsedTrackId;
276505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 8;
276605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 8;
276705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
276805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("fragment header: %08x %08x", flags, mTrackFragmentHeaderInfo.mTrackID);
276905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
277005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent) {
277105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 8) {
277205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
277305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
277405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
277505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset, &mTrackFragmentHeaderInfo.mBaseDataOffset)) {
277605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
277705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
277805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 8;
277905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 8;
278005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
278105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
278205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent) {
278305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
278405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
278505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
278605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
278705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mSampleDescriptionIndex)) {
278805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
278905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
279005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
279105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
279205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
279305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
279405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
279505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
279605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
279705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
279805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
279905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleDuration)) {
280005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
280105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
280205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
280305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
280405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
280505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
280605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
280705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
280805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
280905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
281005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
281105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleSize)) {
281205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
281305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
281405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
281505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
281605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
281705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
281805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
281905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
282005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
282105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
282205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
282305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleFlags)) {
282405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
282505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
282605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
282705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
282805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
282905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
283005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!(flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent)) {
283105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mTrackFragmentHeaderInfo.mBaseDataOffset = mCurrentMoofOffset;
283205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
283305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
283405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mDataOffset = 0;
283505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
283605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
283705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
283805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentRun(off64_t offset, off64_t size) {
283905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
284005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Extractor::parseTrackFragmentRun");
284105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 8) {
284205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
284305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
284405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
284505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    enum {
284605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kDataOffsetPresent                  = 0x01,
284705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kFirstSampleFlagsPresent            = 0x04,
284805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleDurationPresent              = 0x100,
284905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleSizePresent                  = 0x200,
285005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleFlagsPresent                 = 0x400,
285105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleCompositionTimeOffsetPresent = 0x800,
285205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
285305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
285405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
285505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) {
285605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
285705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
285805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("fragment run flags: %08x", flags);
285905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
286005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & 0xff000000) {
286105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
286205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
286305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
286405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if ((flags & kFirstSampleFlagsPresent) && (flags & kSampleFlagsPresent)) {
286505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // These two shall not be used together.
286605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
286705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
286805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
286905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t sampleCount;
287005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, &sampleCount)) {
287105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
287205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
287305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 8;
287405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 8;
287505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
287605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t dataOffset = mTrackFragmentHeaderInfo.mDataOffset;
287705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
287805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t firstSampleFlags = 0;
287905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
288005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kDataOffsetPresent) {
288105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
288205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
288305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
288405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
288505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int32_t dataOffsetDelta;
288605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, (uint32_t*)&dataOffsetDelta)) {
288705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
288805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
288905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
289005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        dataOffset = mTrackFragmentHeaderInfo.mBaseDataOffset + dataOffsetDelta;
289105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
289205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
289305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
289405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
289505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
289605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kFirstSampleFlagsPresent) {
289705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
289805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
289905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
290005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
290105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &firstSampleFlags)) {
290205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
290305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
290405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
290505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
290605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
290705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
290805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t sampleDuration = 0, sampleSize = 0, sampleFlags = 0,
290905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen             sampleCtsOffset = 0;
291005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
291105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size_t bytesPerSample = 0;
291205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleDurationPresent) {
291305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
291405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
291505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
291605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration;
291705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
291805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration;
291905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
292005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
292105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleSizePresent) {
292205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
292305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
292405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
292505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
292605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
292705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
292805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
292905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
293005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleFlagsPresent) {
293105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
293205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
293305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
293405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
293505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
293605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
293705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
293805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
293905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleCompositionTimeOffsetPresent) {
294005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
294105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
294205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleCtsOffset = 0;
294305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
294405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
294505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < sampleCount * bytesPerSample) {
294605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
294705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
294805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
294905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Sample tmp;
295005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    for (uint32_t i = 0; i < sampleCount; ++i) {
295105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleDurationPresent) {
295205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleDuration)) {
295305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
295405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
295505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
295605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
295705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
295805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleSizePresent) {
295905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleSize)) {
296005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
296105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
296205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
296305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
296405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
296505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleFlagsPresent) {
296605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleFlags)) {
296705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
296805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
296905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
297005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
297105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
297205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleCompositionTimeOffsetPresent) {
297305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleCtsOffset)) {
297405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
297505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
297605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
297705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
297805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2979ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        ALOGV("adding sample %d at offset 0x%08llx, size %u, duration %u, "
2980ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen              " flags 0x%08x", i + 1,
298105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dataOffset, sampleSize, sampleDuration,
298205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                (flags & kFirstSampleFlagsPresent) && i == 0
298305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ? firstSampleFlags : sampleFlags);
298405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.offset = dataOffset;
298505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.size = sampleSize;
298605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.duration = sampleDuration;
298705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentSamples.add(tmp);
298805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
298905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        dataOffset += sampleSize;
299005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
299105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
299205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mDataOffset = dataOffset;
299305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
299405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
299505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
299605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
299720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> MPEG4Source::getFormat() {
29987b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
29997b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
300020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return mFormat;
300120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
300220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30036064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const {
30046064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    switch (mNALLengthSize) {
30056064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 1:
30066064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return *data;
30076064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 2:
30086064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U16_AT(data);
30096064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 3:
30106064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return ((size_t)data[0] << 16) | U16_AT(&data[1]);
30116064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 4:
30126064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U32_AT(data);
30136064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
30146064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
30156064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // This cannot happen, mNALLengthSize springs to life by adding 1 to
30166064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // a 2-bit integer.
30176064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    CHECK(!"Should not be here.");
30186064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
30196064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    return 0;
30206064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber}
30216064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
302220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::read(
302320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
30247b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
30257b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
3026dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
302720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
302805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mFirstMoofOffset > 0) {
302905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return fragmentedRead(out, options);
303005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
303105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
303220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *out = NULL;
303320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3034abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    int64_t targetSampleTimeUs = -1;
3035abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
303620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t seekTimeUs;
3037abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
3038abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
3039abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t findFlags = 0;
3040abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        switch (mode) {
3041abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_PREVIOUS_SYNC:
3042abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagBefore;
3043abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3044abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_NEXT_SYNC:
3045abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagAfter;
3046abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3047abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST_SYNC:
3048abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST:
3049abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagClosest;
3050abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3051abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            default:
3052abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                CHECK(!"Should not be here.");
3053abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3054abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3055abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
305620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        uint32_t sampleIndex;
3057abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        status_t err = mSampleTable->findSampleAtTime(
305820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                seekTimeUs * mTimescale / 1000000,
3059abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                &sampleIndex, findFlags);
3060abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3061abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
3062abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // We found the closest sample already, now we want the sync
3063abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // sample preceding it (or the sample itself of course), even
3064abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // if the subsequent sync sample is closer.
3065abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            findFlags = SampleTable::kFlagBefore;
3066abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3067abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3068abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleIndex;
3069abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (err == OK) {
3070abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            err = mSampleTable->findSyncSampleNear(
3071abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    sampleIndex, &syncSampleIndex, findFlags);
3072abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
307320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3074788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        uint32_t sampleTime;
3075788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        if (err == OK) {
3076788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber            err = mSampleTable->getMetaDataForSample(
3077788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber                    sampleIndex, NULL, NULL, &sampleTime);
3078788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        }
3079788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber
308020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (err != OK) {
30815295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            if (err == ERROR_OUT_OF_RANGE) {
30825295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // An attempt to seek past the end of the stream would
30835295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // normally cause this ERROR_OUT_OF_RANGE error. Propagating
30845295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // this all the way to the MediaPlayer would cause abnormal
30855295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // termination. Legacy behaviour appears to be to behave as if
30865295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // we had seeked to the end of stream, ending normally.
30875295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                err = ERROR_END_OF_STREAM;
30885295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            }
308905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("end of stream");
309020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return err;
309120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
309220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3093abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
3094abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
3095abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3096abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3097abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#if 0
3098abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleTime;
3099abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
3100abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    syncSampleIndex, NULL, NULL, &syncSampleTime));
3101abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3102df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("seek to time %lld us => sample at time %lld us, "
3103abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             "sync sample at time %lld us",
3104abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             seekTimeUs,
3105abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             sampleTime * 1000000ll / mTimescale,
3106abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             syncSampleTime * 1000000ll / mTimescale);
3107abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#endif
3108abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3109abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        mCurrentSampleIndex = syncSampleIndex;
311020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mBuffer != NULL) {
311120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
311220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
311320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
311420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
311520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // fall through
311620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
311720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3118c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset;
31190024245e134467d120b40099da16c467dc365e76Andreas Huber    size_t size;
31204678a6dc5f09008481524949a9667af5a6190374Andreas Huber    uint32_t cts;
31218bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    bool isSyncSample;
3122dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool newBuffer = false;
3123dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (mBuffer == NULL) {
3124dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        newBuffer = true;
312520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3126c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        status_t err =
3127c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber            mSampleTable->getMetaDataForSample(
31284678a6dc5f09008481524949a9667af5a6190374Andreas Huber                    mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample);
312920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3130dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
3131dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
3132dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3133dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3134dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        err = mGroup->acquire_buffer(&mBuffer);
3135c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
3136dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
3137ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            CHECK(mBuffer == NULL);
3138dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
3139dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
31400024245e134467d120b40099da16c467dc365e76Andreas Huber    }
314120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3142dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (!mIsAVC || mWantsNALFragments) {
3143dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (newBuffer) {
3144dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ssize_t num_bytes_read =
314534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
3146dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3147dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            if (num_bytes_read < (ssize_t)size) {
3148dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer->release();
3149dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer = NULL;
3150dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3151dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                return ERROR_IO;
3152dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            }
3153dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
31547b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber            CHECK(mBuffer != NULL);
3155dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->set_range(0, size);
3156dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->meta_data()->clear();
315748c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mBuffer->meta_data()->setInt64(
31584678a6dc5f09008481524949a9667af5a6190374Andreas Huber                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
3159abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3160abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            if (targetSampleTimeUs >= 0) {
3161abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                mBuffer->meta_data()->setInt64(
3162abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                        kKeyTargetTime, targetSampleTimeUs);
3163abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            }
3164abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
31658bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            if (isSyncSample) {
31668bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
31678bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            }
31688bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
3169dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ++mCurrentSampleIndex;
3170dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3171dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3172dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (!mIsAVC) {
3173dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            *out = mBuffer;
3174dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
3175dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3176dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return OK;
3177dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3178dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3179dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Each NAL unit is split up into its constituent fragments and
3180dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // each one of them returned in its own buffer.
3181dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
31826064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(mBuffer->range_length() >= mNALLengthSize);
3183dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3184dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        const uint8_t *src =
3185dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
3186dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
31876064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t nal_size = parseNALSize(src);
3188e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
318929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("incomplete NAL unit.");
3190e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3191e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer->release();
3192e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer = NULL;
3193e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3194e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            return ERROR_MALFORMED;
3195e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        }
3196dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3197dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        MediaBuffer *clone = mBuffer->clone();
31987b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(clone != NULL);
31996064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
3200dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
32017b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(mBuffer != NULL);
3202dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mBuffer->set_range(
32036064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_offset() + mNALLengthSize + nal_size,
32046064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_length() - mNALLengthSize - nal_size);
3205dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3206dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (mBuffer->range_length() == 0) {
3207dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->release();
3208dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
3209dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3210dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3211dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        *out = clone;
3212dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3213dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        return OK;
3214dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    } else {
3215dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Whole NAL units are returned but each fragment is prefixed by
3216dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // the start code (0x00 00 00 01).
3217dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        ssize_t num_bytes_read = 0;
3218dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        int32_t drm = 0;
3219dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
3220dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (usesDRM) {
3221dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            num_bytes_read =
3222dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
3223dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
3224dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
3225dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
322620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
322720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (num_bytes_read < (ssize_t)size) {
322820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
322920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
323020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3231dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return ERROR_IO;
323220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
323320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3234dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (usesDRM) {
3235dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK(mBuffer != NULL);
3236dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            mBuffer->set_range(0, size);
32376064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
3238dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
3239dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            uint8_t *dstData = (uint8_t *)mBuffer->data();
3240dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size_t srcOffset = 0;
3241dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size_t dstOffset = 0;
3242e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3243dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            while (srcOffset < size) {
324434fe252c89e33572d01fea981b58d7b115e76164James Dong                bool isMalFormed = (srcOffset + mNALLengthSize > size);
324534fe252c89e33572d01fea981b58d7b115e76164James Dong                size_t nalLength = 0;
324634fe252c89e33572d01fea981b58d7b115e76164James Dong                if (!isMalFormed) {
324734fe252c89e33572d01fea981b58d7b115e76164James Dong                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
324834fe252c89e33572d01fea981b58d7b115e76164James Dong                    srcOffset += mNALLengthSize;
324934fe252c89e33572d01fea981b58d7b115e76164James Dong                    isMalFormed = srcOffset + nalLength > size;
325034fe252c89e33572d01fea981b58d7b115e76164James Dong                }
3251e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
325234fe252c89e33572d01fea981b58d7b115e76164James Dong                if (isMalFormed) {
325329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                    ALOGE("Video is malformed");
3254dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    mBuffer->release();
3255dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    mBuffer = NULL;
3256dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return ERROR_MALFORMED;
3257dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
3258dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
3259dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                if (nalLength == 0) {
3260dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    continue;
3261dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
3262dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3263dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                CHECK(dstOffset + 4 <= mBuffer->size());
3264dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3265dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3266dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3267dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3268dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 1;
3269dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
3270dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                srcOffset += nalLength;
3271dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstOffset += nalLength;
3272dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
3273dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK_EQ(srcOffset, size);
3274dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK(mBuffer != NULL);
3275dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            mBuffer->set_range(0, dstOffset);
3276dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3277dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
327820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->meta_data()->clear();
327948c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        mBuffer->meta_data()->setInt64(
32804678a6dc5f09008481524949a9667af5a6190374Andreas Huber                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
3281abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3282abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (targetSampleTimeUs >= 0) {
3283abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            mBuffer->meta_data()->setInt64(
3284abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    kKeyTargetTime, targetSampleTimeUs);
3285abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3286abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
32878bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        if (isSyncSample) {
32888bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
32898bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        }
32908bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
329120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        ++mCurrentSampleIndex;
329220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
329320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        *out = mBuffer;
329420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
329520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
329620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
329720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
329820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
329920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
330005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::fragmentedRead(
330105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MediaBuffer **out, const ReadOptions *options) {
330205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
330305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Source::fragmentedRead");
330405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
330505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    CHECK(mStarted);
330605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
330705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    *out = NULL;
330805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
330905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t targetSampleTimeUs = -1;
331005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
331105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t seekTimeUs;
331205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ReadOptions::SeekMode mode;
331305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
331405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
331505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int numSidxEntries = mSegments.size();
331605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (numSidxEntries != 0) {
331705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            int64_t totalTime = 0;
331805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t totalOffset = mFirstMoofOffset;
331905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            for (int i = 0; i < numSidxEntries; i++) {
332005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                const SidxEntry *se = &mSegments[i];
332105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (totalTime + se->mDurationUs > seekTimeUs) {
332205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    // The requested time is somewhere in this segment
332305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    if ((mode == ReadOptions::SEEK_NEXT_SYNC) ||
332405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        (mode == ReadOptions::SEEK_CLOSEST_SYNC &&
332505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        (seekTimeUs - totalTime) > (totalTime + se->mDurationUs - seekTimeUs))) {
332605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        // requested next sync, or closest sync and it was closer to the end of
332705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        // this segment
332805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        totalTime += se->mDurationUs;
332905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        totalOffset += se->mSize;
333005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    }
333105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    break;
333205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
333305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                totalTime += se->mDurationUs;
333405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                totalOffset += se->mSize;
333505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
333605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentMoofOffset = totalOffset;
333705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentSamples.clear();
333805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentSampleIndex = 0;
333905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        parseChunk(&totalOffset);
334005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentTime = totalTime * mTimescale / 1000000ll;
334105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
334205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
334305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer != NULL) {
334405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
334505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
334605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
334705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
334805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // fall through
334905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
335005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
335105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t offset = 0;
335205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size_t size;
335305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t cts = 0;
335405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    bool isSyncSample = false;
335505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    bool newBuffer = false;
335605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mBuffer == NULL) {
335705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        newBuffer = true;
335805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
335905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mCurrentSampleIndex >= mCurrentSamples.size()) {
336005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            // move to next fragment
336105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            Sample lastSample = mCurrentSamples[mCurrentSamples.size() - 1];
336205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t nextMoof = mNextMoofOffset; // lastSample.offset + lastSample.size;
336305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentMoofOffset = nextMoof;
336405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentSamples.clear();
336505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentSampleIndex = 0;
336605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            parseChunk(&nextMoof);
336705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (mCurrentSampleIndex >= mCurrentSamples.size()) {
336805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return ERROR_END_OF_STREAM;
336905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
337005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
337105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
337205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
337305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset = smpl->offset;
337405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size = smpl->size;
337505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        cts = mCurrentTime;
337605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentTime += smpl->duration;
337705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        isSyncSample = (mCurrentSampleIndex == 0); // XXX
337805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
337905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        status_t err = mGroup->acquire_buffer(&mBuffer);
338005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
338105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (err != OK) {
338205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer == NULL);
338305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("acquire_buffer returned %d", err);
338405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return err;
338505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
338605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
338705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
338848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
338948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    const sp<MetaData> bufmeta = mBuffer->meta_data();
339048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    bufmeta->clear();
339148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (smpl->encryptedsizes.size()) {
339248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // store clear/encrypted lengths in metadata
339348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyPlainSizes, 0,
339448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->clearsizes.array(), smpl->clearsizes.size() * 4);
339548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyEncryptedSizes, 0,
339648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
339748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
339848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
339948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setInt32(kKeyCryptoMode, mCryptoMode);
340048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16);
340148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
340248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
340305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mIsAVC || mWantsNALFragments) {
340405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (newBuffer) {
340505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ssize_t num_bytes_read =
340605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
340705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
340805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (num_bytes_read < (ssize_t)size) {
340905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->release();
341005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer = NULL;
341105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
341205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                ALOGV("i/o error");
341305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_IO;
341405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
341505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
341605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
341705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, size);
341805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt64(
341905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
342005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
342105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (targetSampleTimeUs >= 0) {
342205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->meta_data()->setInt64(
342305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        kKeyTargetTime, targetSampleTimeUs);
342405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
342505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
342605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (isSyncSample) {
342705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
342805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
342905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
343005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ++mCurrentSampleIndex;
343105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
343205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
343305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mIsAVC) {
343405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *out = mBuffer;
343505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
343605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
343705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return OK;
343805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
343905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
344005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // Each NAL unit is split up into its constituent fragments and
344105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // each one of them returned in its own buffer.
344205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
344305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(mBuffer->range_length() >= mNALLengthSize);
344405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
344505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const uint8_t *src =
344605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
344705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
344805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size_t nal_size = parseNALSize(src);
344905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
345005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGE("incomplete NAL unit.");
345105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
345205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
345305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
345405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
345505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
345605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
345705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
345805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MediaBuffer *clone = mBuffer->clone();
345905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(clone != NULL);
346005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
346105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
346205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(mBuffer != NULL);
346305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer->set_range(
346405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->range_offset() + mNALLengthSize + nal_size,
346505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->range_length() - mNALLengthSize - nal_size);
346605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
346705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer->range_length() == 0) {
346805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
346905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
347005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
347105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
347205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        *out = clone;
347305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
347405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
347505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
347605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV("whole NAL");
347705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // Whole NAL units are returned but each fragment is prefixed by
347805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // the start code (0x00 00 00 01).
347905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ssize_t num_bytes_read = 0;
348005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int32_t drm = 0;
348105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
348205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (usesDRM) {
348305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            num_bytes_read =
348405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
348505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else {
348605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
348705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
348805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
348905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (num_bytes_read < (ssize_t)size) {
349005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
349105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
349205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
349305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("i/o error");
349405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_IO;
349505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
349605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
349705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (usesDRM) {
349805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
349905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, size);
350005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
350105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else {
350205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            uint8_t *dstData = (uint8_t *)mBuffer->data();
350305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            size_t srcOffset = 0;
350405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            size_t dstOffset = 0;
350505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
350605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            while (srcOffset < size) {
350705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                bool isMalFormed = (srcOffset + mNALLengthSize > size);
350805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                size_t nalLength = 0;
350905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (!isMalFormed) {
351005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
351105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    srcOffset += mNALLengthSize;
351205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    isMalFormed = srcOffset + nalLength > size;
351305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
351405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
351505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (isMalFormed) {
351605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ALOGE("Video is malformed");
351705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    mBuffer->release();
351805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    mBuffer = NULL;
351905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return ERROR_MALFORMED;
352005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
352105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
352205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (nalLength == 0) {
352305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    continue;
352405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
352505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
352605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                CHECK(dstOffset + 4 <= mBuffer->size());
352705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
352805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
352905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
353005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
353105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 1;
353205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
353305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                srcOffset += nalLength;
353405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstOffset += nalLength;
353505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
353605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK_EQ(srcOffset, size);
353705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
353805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, dstOffset);
353905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
354005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
354105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer->meta_data()->setInt64(
354205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
354305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
354405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (targetSampleTimeUs >= 0) {
354505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt64(
354605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    kKeyTargetTime, targetSampleTimeUs);
354705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
354805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
354905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (isSyncSample) {
355005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
355105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
355205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
355305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ++mCurrentSampleIndex;
355405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
355505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        *out = mBuffer;
355605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer = NULL;
355705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
355805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
355905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
356005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
356105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3562bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas HuberMPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix(
3563bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        const char *mimePrefix) {
3564bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    for (Track *track = mFirstTrack; track != NULL; track = track->next) {
3565bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        const char *mime;
3566bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        if (track->meta != NULL
3567bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                && track->meta->findCString(kKeyMIMEType, &mime)
3568bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) {
3569bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber            return track;
3570bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        }
3571bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    }
3572bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber
3573bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    return NULL;
3574bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber}
3575bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber
35761b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool LegacySniffMPEG4(
3577693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
357820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[8];
357920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
358034769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    ssize_t n = source->readAt(4, header, sizeof(header));
358120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (n < (ssize_t)sizeof(header)) {
358220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return false;
358320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
358420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
358520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
3586b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8)
3587b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8)
35880dba73763a04d39faf999dcc5ef12af3c99535a7Andreas Huber        || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
3589ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
3590983b449a27b5fa91eca82ede5204b4341899be62Andreas Huber        || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
359118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
35925a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        *confidence = 0.4;
359320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
359420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return true;
359520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
359620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
359720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return false;
359820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
359920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36001b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool isCompatibleBrand(uint32_t fourcc) {
36011b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    static const uint32_t kCompatibleBrands[] = {
36021b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', 'm'),
36031b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', '2'),
36041b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('a', 'v', 'c', '1'),
36051b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('3', 'g', 'p', '4'),
36061b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '1'),
36071b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '2'),
36084cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong
36094cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        // Won't promise that the following file types can be played.
36104cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        // Just give these file types a chance.
36114cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        FOURCC('q', 't', ' ', ' '),  // Apple's QuickTime
36124cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        FOURCC('M', 'S', 'N', 'V'),  // Sony's PSP
361358fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber
361458fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber        FOURCC('3', 'g', '2', 'a'),  // 3GPP2
361558fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber        FOURCC('3', 'g', '2', 'b'),
36161b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    };
36171b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
36181b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    for (size_t i = 0;
36191b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]);
36201b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         ++i) {
36211b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        if (kCompatibleBrands[i] == fourcc) {
36221b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            return true;
36231b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
36241b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
36251b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
36261b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
36271b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
36281b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
36291b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// Attempt to actually parse the 'ftyp' atom and determine if a suitable
36301b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// compatible brand is present.
3631a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// Also try to identify where this file's metadata ends
3632a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// (end of the 'moov' atom) and report it to the caller as part of
3633a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// the metadata.
36341b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool BetterSniffMPEG4(
3635a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
3636a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        sp<AMessage> *meta) {
3637a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    // We scan up to 128 bytes to identify this file as an MP4.
3638a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    static const off64_t kMaxScanOffset = 128ll;
36391b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
3640a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    off64_t offset = 0ll;
3641a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    bool foundGoodFileType = false;
3642a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    off64_t moovAtomEndOffset = -1ll;
3643a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    bool done = false;
36441b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
3645a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    while (!done && offset < kMaxScanOffset) {
3646a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint32_t hdr[2];
3647a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        if (source->readAt(offset, hdr, 8) < 8) {
3648a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            return false;
3649a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        }
3650a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3651a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint64_t chunkSize = ntohl(hdr[0]);
3652a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint32_t chunkType = ntohl(hdr[1]);
3653a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        off64_t chunkDataOffset = offset + 8;
3654a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3655a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        if (chunkSize == 1) {
3656a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            if (source->readAt(offset + 8, &chunkSize, 8) < 8) {
36571b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                return false;
36581b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
36591b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
3660a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            chunkSize = ntoh64(chunkSize);
3661a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            chunkDataOffset += 8;
3662a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3663a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            if (chunkSize < 16) {
3664a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                // The smallest valid chunk is 16 bytes long in this case.
3665a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                return false;
3666a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            }
3667a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        } else if (chunkSize < 8) {
3668a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            // The smallest valid chunk is 8 bytes long.
3669a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            return false;
3670a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        }
3671a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3672a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        off64_t chunkDataSize = offset + chunkSize - chunkDataOffset;
3673a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
367405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        char chunkstring[5];
367505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MakeFourCCString(chunkType, chunkstring);
367605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV("saw chunk type %s, size %lld @ %lld", chunkstring, chunkSize, offset);
3677a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        switch (chunkType) {
3678a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            case FOURCC('f', 't', 'y', 'p'):
3679a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            {
3680a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                if (chunkDataSize < 8) {
3681a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    return false;
3682a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
3683a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3684a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4;
3685a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
3686a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (i == 1) {
3687a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        // Skip this index, it refers to the minorVersion,
3688a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        // not a brand.
3689a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        continue;
3690a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
3691a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3692a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    uint32_t brand;
3693a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (source->readAt(
3694a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                                chunkDataOffset + 4 * i, &brand, 4) < 4) {
3695a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        return false;
3696a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
3697a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3698a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    brand = ntohl(brand);
3699a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3700a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (isCompatibleBrand(brand)) {
3701a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        foundGoodFileType = true;
3702a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        break;
3703a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
3704a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
3705a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3706a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                if (!foundGoodFileType) {
3707a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    return false;
3708a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
3709a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
37101b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                break;
37111b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
3712a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3713a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            case FOURCC('m', 'o', 'o', 'v'):
3714a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            {
3715a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                moovAtomEndOffset = offset + chunkSize;
3716a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3717a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                done = true;
3718a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                break;
3719a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            }
3720a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3721a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            default:
3722a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                break;
37231b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
3724a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3725a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        offset += chunkSize;
37261b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
37271b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
3728a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (!foundGoodFileType) {
37291b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return false;
37301b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
37311b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
37321b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
37335a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber    *confidence = 0.4f;
37341b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
3735a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (moovAtomEndOffset >= 0) {
3736a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        *meta = new AMessage;
3737a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        (*meta)->setInt64("meta-data-size", moovAtomEndOffset);
3738a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3739456caf3f5f0af673dc120c17c23635f40d8f5ac2Andreas Huber        ALOGV("found metadata size: %lld", moovAtomEndOffset);
3740a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    }
3741a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
37421b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return true;
37431b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
37441b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
37451b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberbool SniffMPEG4(
37465a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
3747a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        sp<AMessage> *meta) {
3748a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (BetterSniffMPEG4(source, mimeType, confidence, meta)) {
37491b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
37501b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
37511b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
37521b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    if (LegacySniffMPEG4(source, mimeType, confidence)) {
37535ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Identified supported mpeg4 through LegacySniffMPEG4.");
37541b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
37551b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
37561b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
37571b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
37581b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
37591b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
376020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
3761