MPEG4Extractor.cpp revision 0517e0b6e4a86f34388631416dd6b3b4fcb91ff8
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
41fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé#include <byteswap.h>
42328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé#include "include/ID3.h"
43fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Source : public MediaSource {
4720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Caller retains ownership of both "dataSource" and "sampleTable".
49693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    MPEG4Source(const sp<MetaData> &format,
50693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber                const sp<DataSource> &dataSource,
5148c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                int32_t timeScale,
5205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                const sp<SampleTable> &sampleTable,
5305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                Vector<SidxEntry> &sidx,
5405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                off64_t firstMoofOffset);
5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t start(MetaData *params = NULL);
5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t stop();
5820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual sp<MetaData> getFormat();
6020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL);
6205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    virtual status_t fragmentedRead(MediaBuffer **buffer, const ReadOptions *options = NULL);
6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huberprotected:
65693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    virtual ~MPEG4Source();
66693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber
6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
687b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex mLock;
697b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
7020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mFormat;
71693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<DataSource> mDataSource;
7220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t mTimescale;
73693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<SampleTable> mSampleTable;
7420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t mCurrentSampleIndex;
7505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t mCurrentFragmentIndex;
7605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Vector<SidxEntry> &mSegments;
7705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mFirstMoofOffset;
7805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mCurrentMoofOffset;
7905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mNextMoofOffset;
8005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t mCurrentTime;
8105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int32_t mLastParsedTrackId;
8205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int32_t mTrackId;
8320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
84ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int32_t mCryptoMode;    // passed in from extractor
85ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int32_t mDefaultIVSize; // passed in from extractor
86ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t mCryptoKey[16]; // passed in from extractor
87ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentAuxInfoType;
88ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentAuxInfoTypeParameter;
8948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    int32_t mCurrentDefaultSampleInfoSize;
90ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoCount;
91ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoAllocSize;
92ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t* mCurrentSampleInfoSizes;
93ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoOffsetCount;
94ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoOffsetsAllocSize;
95ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint64_t* mCurrentSampleInfoOffsets;
96ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
9720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mIsAVC;
986064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    size_t mNALLengthSize;
996064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
10020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mStarted;
10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBufferGroup *mGroup;
10320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *mBuffer;
10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
106dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool mWantsNALFragments;
10720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1080024245e134467d120b40099da16c467dc365e76Andreas Huber    uint8_t *mSrcBuffer;
1090024245e134467d120b40099da16c467dc365e76Andreas Huber
1106064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    size_t parseNALSize(const uint8_t *data) const;
11105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseChunk(off64_t *offset);
11205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseTrackFragmentHeader(off64_t offset, off64_t size);
11305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseTrackFragmentRun(off64_t offset, off64_t size);
114ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    status_t parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size);
115ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    status_t parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size);
11605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
11705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    struct TrackFragmentHeaderInfo {
11805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        enum Flags {
11905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kBaseDataOffsetPresent         = 0x01,
12005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kSampleDescriptionIndexPresent = 0x02,
12105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleDurationPresent  = 0x08,
12205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleSizePresent      = 0x10,
12305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleFlagsPresent     = 0x20,
12405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDurationIsEmpty               = 0x10000,
12505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        };
12605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
12705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mTrackID;
12805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mFlags;
12905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint64_t mBaseDataOffset;
13005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mSampleDescriptionIndex;
13105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleDuration;
13205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleSize;
13305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleFlags;
13405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
13505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint64_t mDataOffset;
13605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
13705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    TrackFragmentHeaderInfo mTrackFragmentHeaderInfo;
13805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
13905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    struct Sample {
14005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t offset;
14105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size_t size;
14205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t duration;
143ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        uint8_t iv[16];
144ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Vector<size_t> clearsizes;
145ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Vector<size_t> encryptedsizes;
14605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
14705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Vector<Sample> mCurrentSamples;
1486064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
14920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source(const MPEG4Source &);
15020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source &operator=(const MPEG4Source &);
15120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
15220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This custom data source wraps an existing one and satisfies requests
15450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// falling entirely within a cached range from the cache while forwarding
15550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// all remaining requests to the wrapped datasource.
15650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This is used to cache the full sampletable metadata for a single track,
15750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// possibly wrapping multiple times to cover all tracks, i.e.
15850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// Each MPEG4DataSource caches the sampletable metadata for a single track.
15950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
16050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstruct MPEG4DataSource : public DataSource {
16150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource(const sp<DataSource> &source);
16250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
16350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual status_t initCheck() const;
164c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
165c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    virtual status_t getSize(off64_t *size);
16650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual uint32_t flags();
16750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
168c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    status_t setCachedRange(off64_t offset, size_t size);
16950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprotected:
17150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual ~MPEG4DataSource();
17250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprivate:
17450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex mLock;
17550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    sp<DataSource> mSource;
177c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t mCachedOffset;
17850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    size_t mCachedSize;
17950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    uint8_t *mCache;
18050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    void clearCache();
18250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource(const MPEG4DataSource &);
18450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource &operator=(const MPEG4DataSource &);
18550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber};
18650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source)
18850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    : mSource(source),
18950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCachedOffset(0),
19050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCachedSize(0),
19150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCache(NULL) {
19250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
19350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::~MPEG4DataSource() {
19550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    clearCache();
19650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
19750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Hubervoid MPEG4DataSource::clearCache() {
19950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (mCache) {
20050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        free(mCache);
20150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        mCache = NULL;
20250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
20350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
20450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedOffset = 0;
20550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedSize = 0;
20650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
20750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
20850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstatus_t MPEG4DataSource::initCheck() const {
20950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->initCheck();
21050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
21150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
212c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongssize_t MPEG4DataSource::readAt(off64_t offset, void *data, size_t size) {
21350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex::Autolock autoLock(mLock);
21450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
21550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (offset >= mCachedOffset
21650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            && offset + size <= mCachedOffset + mCachedSize) {
21750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        memcpy(data, &mCache[offset - mCachedOffset], size);
21850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return size;
21950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
22050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
22150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->readAt(offset, data, size);
22250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
22350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
224c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4DataSource::getSize(off64_t *size) {
22550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->getSize(size);
22650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
22750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
22850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberuint32_t MPEG4DataSource::flags() {
22950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->flags();
23050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
23150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
232c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4DataSource::setCachedRange(off64_t offset, size_t size) {
23350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex::Autolock autoLock(mLock);
23450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
23550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    clearCache();
23650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
23750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCache = (uint8_t *)malloc(size);
23850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
23950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (mCache == NULL) {
24050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return -ENOMEM;
24150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
24250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
24350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedOffset = offset;
24450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedSize = size;
24550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
24650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    ssize_t err = mSource->readAt(mCachedOffset, mCache, mCachedSize);
24750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
24850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (err < (ssize_t)size) {
24950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        clearCache();
25050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
25150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return ERROR_IO;
25250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
25350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
25450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return OK;
25550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
25650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
25750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber////////////////////////////////////////////////////////////////////////////////
25850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
25920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatic void hexdump(const void *_data, size_t size) {
26020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const uint8_t *data = (const uint8_t *)_data;
26120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t offset = 0;
26220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (offset < size) {
263377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        printf("0x%04zx  ", offset);
26420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        size_t n = size - offset;
26620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (n > 16) {
26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            n = 16;
26820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
26920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < 16; ++i) {
27120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (i == 8) {
27220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(" ");
27320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
27420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (offset + i < size) {
27620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%02x ", data[offset + i]);
27720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("   ");
27920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
28020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
28120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf(" ");
28320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < n; ++i) {
28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (isprint(data[offset + i])) {
28620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%c", data[offset + i]);
28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
28820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(".");
28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
29020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf("\n");
29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        offset += 16;
29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huberstatic const char *FourCC2MIME(uint32_t fourcc) {
29920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch (fourcc) {
30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
30118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AAC;
30220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
30418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_NB;
30520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
306371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
30718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_WB;
308371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
30920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
31018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_MPEG4;
31120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
313e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('h', '2', '6', '3'):
314e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('H', '2', '6', '3'):
31518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_H263;
31620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
31818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_AVC;
31920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
321dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(!"should not be here.");
32220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
32320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
32420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
32520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissenstatic bool AdjustChannelsAndRate(uint32_t fourcc, uint32_t *channels, uint32_t *rate) {
32748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, FourCC2MIME(fourcc))) {
32848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // AMR NB audio is always mono, 8kHz
32948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *channels = 1;
33048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *rate = 8000;
33148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return true;
33248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, FourCC2MIME(fourcc))) {
33348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // AMR WB audio is always mono, 16kHz
33448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *channels = 1;
33548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *rate = 16000;
33648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return true;
33748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
33848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    return false;
33948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen}
34048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
341693d271e62a3726689ff68f4505ba49228eb94b2Andreas HuberMPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
34205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    : mSidxDuration(0),
34305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mMoofOffset(0),
34405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mDataSource(source),
345bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber      mInitCheck(NO_INIT),
3467be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber      mHasVideo(false),
347fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen      mHeaderTimescale(0),
34820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mFirstTrack(NULL),
34972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber      mLastTrack(NULL),
350dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mFileMetaData(new MetaData),
351dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mFirstSINF(NULL),
352dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mIsDrm(false) {
35320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
35420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Extractor::~MPEG4Extractor() {
35620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        Track *next = track->next;
35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete track;
36120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = next;
36220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
36320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFirstTrack = mLastTrack = NULL;
364dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
365dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    SINF *sinf = mFirstSINF;
366dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (sinf) {
367dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        SINF *next = sinf->next;
368dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        delete sinf->IPMPData;
369dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        delete sinf;
370dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf = next;
371dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
372dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    mFirstSINF = NULL;
373ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
374ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mPssh.size(); i++) {
375ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        delete [] mPssh[i].data;
376ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
37720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
37820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenuint32_t MPEG4Extractor::flags() const {
38005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return CAN_PAUSE |
38105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ((mMoofOffset == 0 || mSidxEntries.size() != 0) ?
38205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    (CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK) : 0);
38305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
38405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3857be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Hubersp<MetaData> MPEG4Extractor::getMetaData() {
3867be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    status_t err;
3877be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    if ((err = readMetaData()) != OK) {
38872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return new MetaData;
3897be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    }
3907be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
39172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return mFileMetaData;
3927be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber}
3937be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
394693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersize_t MPEG4Extractor::countTracks() {
39520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
39620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
397ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        ALOGV("MPEG4Extractor::countTracks: no tracks");
398693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return 0;
39920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
40020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
401693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    size_t n = 0;
40220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
40320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
404693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        ++n;
40520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
40620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
40720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
408ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("MPEG4Extractor::countTracks: %d tracks", n);
409693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    return n;
41020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
41120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4127e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Hubersp<MetaData> MPEG4Extractor::getTrackMetaData(
4137e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        size_t index, uint32_t flags) {
41420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
41520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
41620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return NULL;
41720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
41820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
41920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
42020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
42120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
42220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
42320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
42420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
42520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
42620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
42720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
42820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
429371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
430371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
431371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
432371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
4337e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    if ((flags & kIncludeExtensiveMetaData)
4347e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            && !track->includes_expensive_metadata) {
4357e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        track->includes_expensive_metadata = true;
4367e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
4377e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        const char *mime;
4387e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        CHECK(track->meta->findCString(kKeyMIMEType, &mime));
4397e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        if (!strncasecmp("video/", mime, 6)) {
44005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (mMoofOffset > 0) {
44105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                int64_t duration;
44205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (track->meta->findInt64(kKeyDuration, &duration)) {
44305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    // nothing fancy, just pick a frame near 1/4th of the duration
44405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    track->meta->setInt64(
44505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            kKeyThumbnailTime, duration / 4);
44605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
44705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            } else {
44805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t sampleIndex;
44905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t sampleTime;
45005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK
45105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        && track->sampleTable->getMetaDataForSample(
45205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            sampleIndex, NULL /* offset */, NULL /* size */,
45305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            &sampleTime) == OK) {
45405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    track->meta->setInt64(
45505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            kKeyThumbnailTime,
45605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            ((int64_t)sampleTime * 1000000) / track->timescale);
45705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
4587e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            }
4597e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        }
4607e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    }
4617e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
46220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return track->meta;
46320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
46420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
46548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissenstatic void MakeFourCCString(uint32_t x, char *s) {
46648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[0] = x >> 24;
46748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[1] = (x >> 16) & 0xff;
46848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[2] = (x >> 8) & 0xff;
46948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[3] = x & 0xff;
47048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[4] = '\0';
47148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen}
47248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
47320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Extractor::readMetaData() {
474bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    if (mInitCheck != NO_INIT) {
475bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        return mInitCheck;
47620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
47720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
478c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = 0;
47920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
48005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    while (true) {
48105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        err = parseChunk(&offset, 0);
48205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (err == OK) {
48305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            continue;
48405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
48505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
48605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t hdr[2];
48705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mDataSource->readAt(offset, hdr, 8) < 8) {
48805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
48905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
49005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t chunk_type = ntohl(hdr[1]);
4913f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen        if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
49205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            // store the offset of the first segment
49305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mMoofOffset = offset;
4943f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen        } else if (chunk_type != FOURCC('m', 'd', 'a', 't')) {
4953f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            // keep parsing until we get to the data
4963f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            continue;
49705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
49805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        break;
49920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
5007be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
501bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    if (mInitCheck == OK) {
50272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        if (mHasVideo) {
503bc8b5faec8a0a9ad7c8d94945e7b000d63f0afe6Andreas Huber            mFileMetaData->setCString(
504bc8b5faec8a0a9ad7c8d94945e7b000d63f0afe6Andreas Huber                    kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG4);
50572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else {
50672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
50772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
50872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
5094678a6dc5f09008481524949a9667af5a6190374Andreas Huber        mInitCheck = OK;
510bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    } else {
511bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        mInitCheck = err;
51220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
51320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
514bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    CHECK_NE(err, (status_t)NO_INIT);
515ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
516ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // copy pssh data into file metadata
517ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int psshsize = 0;
518ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mPssh.size(); i++) {
519ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        psshsize += 20 + mPssh[i].datalen;
520ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
521ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (psshsize) {
522ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        char *buf = (char*)malloc(psshsize);
523ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        char *ptr = buf;
524ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        for (size_t i = 0; i < mPssh.size(); i++) {
525ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memcpy(ptr, mPssh[i].uuid, 20); // uuid + length
526ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memcpy(ptr + 20, mPssh[i].data, mPssh[i].datalen);
527ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ptr += (20 + mPssh[i].datalen);
528ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
529ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mFileMetaData->setData(kKeyPssh, 'pssh', buf, psshsize);
530ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        free(buf);
531ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
532bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    return mInitCheck;
53320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
53420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
535dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wangchar* MPEG4Extractor::getDrmTrackInfo(size_t trackID, int *len) {
536dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mFirstSINF == NULL) {
537dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return NULL;
538dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
539dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
540dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    SINF *sinf = mFirstSINF;
541dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (sinf && (trackID != sinf->trackID)) {
542dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf = sinf->next;
543dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
544dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
545dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (sinf == NULL) {
546dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return NULL;
547dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
548dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
549dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    *len = sinf->len;
550dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return sinf->IPMPData;
551dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
552dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
553dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang// Reads an encoded integer 7 bits at a time until it encounters the high bit clear.
55456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenstatic int32_t readSize(off64_t offset,
555dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        const sp<DataSource> DataSource, uint8_t *numOfBytes) {
556dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint32_t size = 0;
557dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t data;
558dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    bool moreData = true;
559dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    *numOfBytes = 0;
560dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
561dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (moreData) {
562dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (DataSource->readAt(offset, &data, 1) < 1) {
563dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return -1;
564dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
565dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        offset ++;
566dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        moreData = (data >= 128) ? true : false;
567dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        size = (size << 7) | (data & 0x7f); // Take last 7 bits
568dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        (*numOfBytes) ++;
569dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
570dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
571dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return size;
572dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
573dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
57484333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG4Extractor::parseDrmSINF(
57584333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        off64_t * /* offset */, off64_t data_offset) {
576dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t updateIdTag;
577dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
578dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
579dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
580dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset ++;
581dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
582dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (0x01/*OBJECT_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
583dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
584dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
585dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
586dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t numOfBytes;
587dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    int32_t size = readSize(data_offset, mDataSource, &numOfBytes);
588dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size < 0) {
589dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
590dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
591dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    int32_t classSize = size;
592dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset += numOfBytes;
593dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
594dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while(size >= 11 ) {
595dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t descriptorTag;
596dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, &descriptorTag, 1) < 1) {
597dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
598dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
599dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset ++;
600dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
601dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (0x11/*OBJECT_DESCRIPTOR_ID_TAG*/ != descriptorTag) {
602dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
603dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
604dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
605dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t buffer[8];
606dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        //ObjectDescriptorID and ObjectDescriptor url flag
607dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, buffer, 2) < 2) {
608dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
609dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
610dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset += 2;
611dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
612dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if ((buffer[1] >> 5) & 0x0001) { //url flag is set
613dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
614dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
615dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
616dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, buffer, 8) < 8) {
617dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
618dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
619dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset += 8;
620dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
621dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if ((0x0F/*ES_ID_REF_TAG*/ != buffer[1])
622dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                || ( 0x0A/*IPMP_DESCRIPTOR_POINTER_ID_TAG*/ != buffer[5])) {
623dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
624dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
625dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
626dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        SINF *sinf = new SINF;
627dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->trackID = U16_AT(&buffer[3]);
628dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->IPMPDescriptorID = buffer[7];
629dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->next = mFirstSINF;
630dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        mFirstSINF = sinf;
631dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
632dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        size -= (8 + 2 + 1);
633dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
634dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
635dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size != 0) {
636dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
637dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
638dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
639dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
640dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
641dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
642dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset ++;
643dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
644dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if(0x05/*IPMP_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
645dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
646dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
647dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
648dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    size = readSize(data_offset, mDataSource, &numOfBytes);
649dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size < 0) {
650dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
651dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
652dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    classSize = size;
653dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset += numOfBytes;
654dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
655dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (size > 0) {
656dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t tag;
657dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        int32_t dataLen;
658dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, &tag, 1) < 1) {
659dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
660dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
661dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset ++;
662dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
663dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (0x0B/*IPMP_DESCRIPTOR_ID_TAG*/ == tag) {
664dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            uint8_t id;
665dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            dataLen = readSize(data_offset, mDataSource, &numOfBytes);
666dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (dataLen < 0) {
667dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
668dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            } else if (dataLen < 4) {
669dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
670dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
671dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset += numOfBytes;
672dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
673dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (mDataSource->readAt(data_offset, &id, 1) < 1) {
674dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
675dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
676dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset ++;
677dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
678dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            SINF *sinf = mFirstSINF;
679dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            while (sinf && (sinf->IPMPDescriptorID != id)) {
680dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                sinf = sinf->next;
681dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
682dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (sinf == NULL) {
683dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
684dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
685dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            sinf->len = dataLen - 3;
686dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            sinf->IPMPData = new char[sinf->len];
687f7df9ab3187a3c02bffe1fba10d3fb95197e4a07Ichitaro Kohara            data_offset += 2;
688dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
689f7df9ab3187a3c02bffe1fba10d3fb95197e4a07Ichitaro Kohara            if (mDataSource->readAt(data_offset, sinf->IPMPData, sinf->len) < sinf->len) {
690dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
691dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
692dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset += sinf->len;
693dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
694dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size -= (dataLen + numOfBytes + 1);
695dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
696dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
697dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
698dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size != 0) {
699dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
700dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
701dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
702dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return UNKNOWN_ERROR;  // Return a dummy error.
703dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
704dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
70572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstruct PathAdder {
70672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder(Vector<uint32_t> *path, uint32_t chunkType)
70772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        : mPath(path) {
70872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        mPath->push(chunkType);
70972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
71072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
71172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    ~PathAdder() {
71272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        mPath->pop();
71372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
71472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
71572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberprivate:
71672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    Vector<uint32_t> *mPath;
71772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
71872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder(const PathAdder &);
71972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder &operator=(const PathAdder &);
72072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber};
72172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
72272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic bool underMetaDataPath(const Vector<uint32_t> &path) {
72372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return path.size() >= 5
72472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[0] == FOURCC('m', 'o', 'o', 'v')
72572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[1] == FOURCC('u', 'd', 't', 'a')
72672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[2] == FOURCC('m', 'e', 't', 'a')
72772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[3] == FOURCC('i', 'l', 's', 't');
72872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
72972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
73072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber// Given a time in seconds since Jan 1 1904, produce a human-readable string.
73172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic void convertTimeToDate(int64_t time_1904, String8 *s) {
73272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    time_t time_1970 = time_1904 - (((66 * 365 + 17) * 24) * 3600);
73372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
73472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    char tmp[32];
73572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", gmtime(&time_1970));
73672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
73772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    s->setTo(tmp);
73872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
73972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
740c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
7415d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    ALOGV("entering parseChunk %lld/%d", *offset, depth);
74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t hdr[2];
74334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
74420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_IO;
74520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
74620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint64_t chunk_size = ntohl(hdr[0]);
74720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t chunk_type = ntohl(hdr[1]);
748c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t data_offset = *offset + 8;
74920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
75020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (chunk_size == 1) {
75134769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
75220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_IO;
75320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
75420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        chunk_size = ntoh64(chunk_size);
75520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        data_offset += 8;
75671b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber
75771b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        if (chunk_size < 16) {
75871b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber            // The smallest valid chunk is 16 bytes long in this case.
75971b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber            return ERROR_MALFORMED;
76071b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        }
76171b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber    } else if (chunk_size < 8) {
76271b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        // The smallest valid chunk is 8 bytes long.
76371b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        return ERROR_MALFORMED;
76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
76520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    char chunk[5];
76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MakeFourCCString(chunk_type, chunk);
76805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("chunk: %s @ %lld, %d", chunk, *offset, depth);
76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#if 0
77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static const char kWhitespace[] = "                                        ";
77220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
77320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size);
77420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    char buffer[256];
776ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    size_t n = chunk_size;
777ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    if (n > sizeof(buffer)) {
778ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        n = sizeof(buffer);
779ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    }
780ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    if (mDataSource->readAt(*offset, buffer, n)
781ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber            < (ssize_t)n) {
782ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        return ERROR_IO;
78320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
784ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
785ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    hexdump(buffer, n);
78620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#endif
78720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
78872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder autoAdder(&mPath, chunk_type);
78972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
790c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t chunk_data_size = *offset + chunk_size - data_offset;
79120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
79272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (chunk_type != FOURCC('c', 'p', 'r', 't')
793515e855eae78aa495da58356486aaa666cb57fd1James Dong            && chunk_type != FOURCC('c', 'o', 'v', 'r')
79472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            && mPath.size() == 5 && underMetaDataPath(mPath)) {
795c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t stop_offset = *offset + chunk_size;
79672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        *offset = data_offset;
79772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        while (*offset < stop_offset) {
79872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            status_t err = parseChunk(offset, depth + 1);
79972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (err != OK) {
80072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return err;
80172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
80272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
803bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
804bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (*offset != stop_offset) {
805bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
806bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
80772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
80872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return OK;
80972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
81072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
81120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch(chunk_type) {
81220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'v'):
81320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'k'):
81420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'i', 'a'):
81520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'i', 'n', 'f'):
81620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('d', 'i', 'n', 'f'):
81720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'b', 'l'):
81820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'v', 'e', 'x'):
81920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'f'):
82020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'f'):
82120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'f', 'r', 'a'):
82272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('u', 'd', 't', 'a'):
82372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('i', 'l', 's', 't'):
824ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'i', 'n', 'f'):
825ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'c', 'h', 'i'):
8260a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        case FOURCC('e', 'd', 't', 's'):
82720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
82850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
8293856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size);
83050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
831b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                if (mDataSource->flags()
832b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                        & (DataSource::kWantsPrefetching
833b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                            | DataSource::kIsCachingDataSource)) {
83450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    sp<MPEG4DataSource> cachedSource =
83550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                        new MPEG4DataSource(mDataSource);
83650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
83750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
83850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                        mDataSource = cachedSource;
83950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    }
84050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                }
8411edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber
8421edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber                mLastTrack->sampleTable = new SampleTable(mDataSource);
84350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            }
84450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
8456f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber            bool isTrack = false;
846bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (chunk_type == FOURCC('t', 'r', 'a', 'k')) {
8476f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                isTrack = true;
8486f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
849bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                Track *track = new Track;
850bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->next = NULL;
851bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                if (mLastTrack) {
852bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    mLastTrack->next = track;
853bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                } else {
854bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    mFirstTrack = track;
855bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                }
856bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                mLastTrack = track;
857bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
858bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->meta = new MetaData;
859bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->includes_expensive_metadata = false;
8606f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                track->skipTrack = false;
861bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->timescale = 0;
862bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->meta->setCString(kKeyMIMEType, "application/octet-stream");
863bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
864bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
865c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
86620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset;
86720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
86820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
86920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
87020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
87120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
87220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
87320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
874bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
875bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
876bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
877bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
8786f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber            if (isTrack) {
8796f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                if (mLastTrack->skipTrack) {
8806f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    Track *cur = mFirstTrack;
8816f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
8826f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    if (cur == mLastTrack) {
8836f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        delete cur;
8846f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        mFirstTrack = mLastTrack = NULL;
8856f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    } else {
8866f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        while (cur && cur->next != mLastTrack) {
8876f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                            cur = cur->next;
8886f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        }
8896f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        cur->next = NULL;
8906f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        delete mLastTrack;
8916f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        mLastTrack = cur;
8926f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    }
8936f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
8946f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    return OK;
8956f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                }
8966f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
897bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                status_t err = verifyTrack(mLastTrack);
898bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
899bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                if (err != OK) {
900bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    return err;
901bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                }
902bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
903bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                mInitCheck = OK;
90420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
905dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                if (!mIsDrm) {
906dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return UNKNOWN_ERROR;  // Return a dummy error.
907dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                } else {
908dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return OK;
909dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
91020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
91120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
91220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
91320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9140a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        case FOURCC('e', 'l', 's', 't'):
9150a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        {
9160517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
9170517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
9180a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            // See 14496-12 8.6.6
9190a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            uint8_t version;
9200a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (mDataSource->readAt(data_offset, &version, 1) < 1) {
9210a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                return ERROR_IO;
9220a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
9230a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9240a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            uint32_t entry_count;
9250a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (!mDataSource->getUInt32(data_offset + 4, &entry_count)) {
9260a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                return ERROR_IO;
9270a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
9280a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9290a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (entry_count != 1) {
9300a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                // we only support a single entry at the moment, for gapless playback
9310a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                ALOGW("ignoring edit list with %d entries", entry_count);
932fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            } else if (mHeaderTimescale == 0) {
933210efd48ed21ca0084d9440f9a1db7d9878f8094Marco Nelissen                ALOGW("ignoring edit list because timescale is 0");
9340a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            } else {
9350a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                off64_t entriesoffset = data_offset + 8;
9360a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                uint64_t segment_duration;
9370a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int64_t media_time;
9380a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9390a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                if (version == 1) {
9400a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    if (!mDataSource->getUInt64(entriesoffset, &segment_duration) ||
9410a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                            !mDataSource->getUInt64(entriesoffset + 8, (uint64_t*)&media_time)) {
9420a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        return ERROR_IO;
9430a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    }
9440a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                } else if (version == 0) {
9450a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    uint32_t sd;
9460a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int32_t mt;
9470a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    if (!mDataSource->getUInt32(entriesoffset, &sd) ||
9480a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                            !mDataSource->getUInt32(entriesoffset + 4, (uint32_t*)&mt)) {
9490a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        return ERROR_IO;
9500a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    }
9510a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    segment_duration = sd;
9520a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    media_time = mt;
9530a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                } else {
9540a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    return ERROR_IO;
9550a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                }
9560a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
957fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                uint64_t halfscale = mHeaderTimescale / 2;
958fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                segment_duration = (segment_duration * 1000000 + halfscale)/ mHeaderTimescale;
959fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                media_time = (media_time * 1000000 + halfscale) / mHeaderTimescale;
9600a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9610a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int64_t duration;
9620a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int32_t samplerate;
9630a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                if (mLastTrack->meta->findInt64(kKeyDuration, &duration) &&
9640a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        mLastTrack->meta->findInt32(kKeySampleRate, &samplerate)) {
9650a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9660a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t delay = (media_time  * samplerate + 500000) / 1000000;
9670a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
9680a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9690a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t paddingus = duration - (segment_duration + media_time);
970465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                    if (paddingus < 0) {
971465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        // track duration from media header (which is what kKeyDuration is) might
972465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        // be slightly shorter than the segment duration, which would make the
973465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        // padding negative. Clamp to zero.
974465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        paddingus = 0;
975465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                    }
9760a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t paddingsamples = (paddingus * samplerate + 500000) / 1000000;
9770a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    mLastTrack->meta->setInt32(kKeyEncoderPadding, paddingsamples);
9780a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                }
9790a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
9800a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            break;
9810a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        }
9820a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
983ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('f', 'r', 'm', 'a'):
984ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
9850517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
9860517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
98748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t original_fourcc;
988ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset, &original_fourcc, 4) < 4) {
989ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
990ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
991ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            original_fourcc = ntohl(original_fourcc);
992ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("read original format: %d", original_fourcc);
993ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc));
99448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t num_channels = 0;
99548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t sample_rate = 0;
99648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (AdjustChannelsAndRate(original_fourcc, &num_channels, &sample_rate)) {
99748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
99848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
99948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            }
1000ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1001ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1002ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1003ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('t', 'e', 'n', 'c'):
1004ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
10050517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
10060517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1007ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (chunk_size < 32) {
1008ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1009ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1010ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1011ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // tenc box contains 1 byte version, 3 byte flags, 3 byte default algorithm id, one byte
1012ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // default IV size, 16 bytes default KeyID
1013ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // (ISO 23001-7)
1014ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            char buf[4];
1015ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memset(buf, 0, 4);
1016ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 4, buf + 1, 3) < 3) {
1017ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1018ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1019ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t defaultAlgorithmId = ntohl(*((int32_t*)buf));
1020ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (defaultAlgorithmId > 1) {
1021ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only 0 (clear) and 1 (AES-128) are valid
1022ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1023ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1024ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1025ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memset(buf, 0, 4);
1026ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 7, buf + 3, 1) < 1) {
1027ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1028ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1029ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t defaultIVSize = ntohl(*((int32_t*)buf));
1030ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1031ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((defaultAlgorithmId == 0 && defaultIVSize != 0) ||
1032ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    (defaultAlgorithmId != 0 && defaultIVSize == 0)) {
1033ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only unencrypted data must have 0 IV size
1034ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1035ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            } else if (defaultIVSize != 0 &&
1036ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    defaultIVSize != 8 &&
1037ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    defaultIVSize != 16) {
1038ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only supported sizes are 0, 8 and 16
1039ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1040ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1041ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1042ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint8_t defaultKeyId[16];
1043ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1044ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 8, &defaultKeyId, 16) < 16) {
1045ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1046ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1047ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1048ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setInt32(kKeyCryptoMode, defaultAlgorithmId);
1049ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setInt32(kKeyCryptoDefaultIVSize, defaultIVSize);
1050ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setData(kKeyCryptoKey, 'tenc', defaultKeyId, 16);
1051ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1052ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1053ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
105420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'k', 'h', 'd'):
105520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
10560517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
10570517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1058ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            status_t err;
1059ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) {
1060ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber                return err;
106120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
106220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
106320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
106420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
106520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1066ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('p', 's', 's', 'h'):
1067ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
10680517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
10690517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1070ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            PsshInfo pssh;
1071ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1072ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 4, &pssh.uuid, 16) < 16) {
1073ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1074ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1075ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1076ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t psshdatalen = 0;
1077ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 20, &psshdatalen, 4) < 4) {
1078ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1079ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1080ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            pssh.datalen = ntohl(psshdatalen);
1081ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("pssh data size: %d", pssh.datalen);
1082ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (pssh.datalen + 20 > chunk_size) {
1083ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // pssh data length exceeds size of containing box
1084ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1085ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1086ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1087ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            pssh.data = new uint8_t[pssh.datalen];
1088ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("allocated pssh @ %p", pssh.data);
1089ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ssize_t requested = (ssize_t) pssh.datalen;
1090ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 24, pssh.data, requested) < requested) {
1091ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1092ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1093ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mPssh.push_back(pssh);
1094ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1095ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1096ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1097ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
109820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'h', 'd'):
109920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
11000517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
11010517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
110220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
110320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
110420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
110520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
110620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t version;
110734769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
110820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, &version, sizeof(version))
110920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(version)) {
111020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
111120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
111220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1113c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t timescale_offset;
111420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
111520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
111620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 16;
111720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else if (version == 0) {
111820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 8;
111920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
112020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
112120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
112220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
112320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t timescale;
112434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
112520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        timescale_offset, &timescale, sizeof(timescale))
112620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(timescale)) {
112720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
112820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
112920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
113020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->timescale = ntohl(timescale);
113120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
113205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            int64_t duration = 0;
113320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
113434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
113520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration, sizeof(duration))
113620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration)) {
113720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
113820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
113920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = ntoh64(duration);
114020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
114105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t duration32;
114234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
114320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration32, sizeof(duration32))
114420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration32)) {
114520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
114620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
114705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // ffmpeg sets duration to -1, which is incorrect.
114805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (duration32 != 0xffffffff) {
114905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    duration = ntohl(duration32);
115005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
115120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
115248c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mLastTrack->meta->setInt64(
115348c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                    kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
115420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11557a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            uint8_t lang[2];
11567a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            off64_t lang_offset;
11577a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            if (version == 1) {
11587a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                lang_offset = timescale_offset + 4 + 8;
11597a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            } else if (version == 0) {
11607a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                lang_offset = timescale_offset + 4 + 4;
11617a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            } else {
11627a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                return ERROR_IO;
11637a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            }
11647a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
11657a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            if (mDataSource->readAt(lang_offset, &lang, sizeof(lang))
11667a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                    < (ssize_t)sizeof(lang)) {
11677a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                return ERROR_IO;
11687a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            }
11697a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
11707a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // To get the ISO-639-2/T three character language code
11717a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // 1 bit pad followed by 3 5-bits characters. Each character
11727a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // is packed as the difference between its ASCII value and 0x60.
11737a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            char lang_code[4];
11747a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[0] = ((lang[0] >> 2) & 0x1f) + 0x60;
11757a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[1] = ((lang[0] & 0x3) << 3 | (lang[1] >> 5)) + 0x60;
11767a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[2] = (lang[1] & 0x1f) + 0x60;
11777a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[3] = '\0';
11787a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
11797a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            mLastTrack->meta->setCString(
11807a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                    kKeyMediaLanguage, lang_code);
11817a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
118220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
118320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
118420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
118520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'd'):
118620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
118720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 8) {
118820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
118920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
119020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
119120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8];
1192c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size < (off64_t)sizeof(buffer)) {
1193bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1194bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
1195bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
119634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
119720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, 8) < 8) {
119820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
119920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
120020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
120120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
120220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
120320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
120420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
120520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
120620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t entry_count = U32_AT(&buffer[4]);
120720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
120820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (entry_count > 1) {
12093b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // For 3GPP timed text, there could be multiple tx3g boxes contain
12103b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // multiple text display formats. These formats will be used to
12113b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // display the timed text.
1212ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // For encrypted files, there may also be more than one entry.
12133b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                const char *mime;
12143b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1215ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) &&
1216ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                        strcasecmp(mime, "application/octet-stream")) {
12173b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    // For now we only support a single type of media per track.
12183b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    mLastTrack->skipTrack = true;
12193b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    *offset += chunk_size;
12203b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    break;
12213b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                }
122220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1223c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
122420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + 8;
122520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            for (uint32_t i = 0; i < entry_count; ++i) {
122620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
122720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
122820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
122920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
123020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1231bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1232bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1233bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1234bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
123520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
123620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
123720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
123820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
123948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        case FOURCC('e', 'n', 'c', 'a'):
124020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
1241371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
124220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
124320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8 + 20];
124420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
124520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic AudioSampleEntry size.
124620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
124720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
124820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
124934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
125020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
125120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
125220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
125320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
125420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
125548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t num_channels = U16_AT(&buffer[16]);
125620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
125781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint16_t sample_size = U16_AT(&buffer[18]);
125881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
125981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
126048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (chunk_type != FOURCC('e', 'n', 'c', 'a')) {
126148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                // if the chunk type is enca, we'll get the type from the sinf/frma box later
126248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
126348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate);
126420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
126548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            ALOGV("*** coding='%s' %d channels, size %d, rate %d\n",
126681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                   chunk, num_channels, sample_size, sample_rate);
126720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
126820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
126920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1270c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
127120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
127220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
127320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
127420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
127520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
127620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
127720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1278bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1279bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1280bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1281bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
128220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
128320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
128420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
128520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
1286ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('e', 'n', 'c', 'v'):
128720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
1288e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('H', '2', '6', '3'):
1289e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('h', '2', '6', '3'):
129020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
129120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
12927be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber            mHasVideo = true;
12937be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
129420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[78];
129520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
129620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic VideoSampleEntry size.
129720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
129820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
129920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
130034769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
130120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
130220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
130320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
130420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
130520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
130620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t width = U16_AT(&buffer[6 + 18]);
130720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t height = U16_AT(&buffer[6 + 20]);
130820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1309ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // The video sample is not standard-compliant if it has invalid dimension.
1310a6256238d9015c42129fe43791968768fe501efaJames Dong            // Use some default width and height value, and
1311a6256238d9015c42129fe43791968768fe501efaJames Dong            // let the decoder figure out the actual width and height (and thus
1312a6256238d9015c42129fe43791968768fe501efaJames Dong            // be prepared for INFO_FOMRAT_CHANGED event).
1313a6256238d9015c42129fe43791968768fe501efaJames Dong            if (width == 0)  width  = 352;
1314a6256238d9015c42129fe43791968768fe501efaJames Dong            if (height == 0) height = 288;
1315a6256238d9015c42129fe43791968768fe501efaJames Dong
1316134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            // printf("*** coding='%s' width=%d height=%d\n",
1317134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            //        chunk, width, height);
131820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1319ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (chunk_type != FOURCC('e', 'n', 'c', 'v')) {
1320ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // if the chunk type is encv, we'll get the type from the sinf/frma box later
1321ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
1322ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
132320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyWidth, width);
132420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyHeight, height);
132520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1326c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
132720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
132820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
132920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
133020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
133120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
133220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
133320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1334bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1335bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1336bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1337bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
133820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
133920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
134020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
134120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'c', 'o'):
134220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('c', 'o', '6', '4'):
134320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
134420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
134520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setChunkOffsetParams(
134620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
134720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13480517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
13490517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
135020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
135120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
135220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
135320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
135420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
135520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
135720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'c'):
135820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
135920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
136020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleToChunkParams(
136120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
136220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13630517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
13640517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
136520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
136620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
136720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
136820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
136920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
137020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
137120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
137220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'z'):
137320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'z', '2'):
137420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
137520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
137620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleSizeParams(
137720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
137820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13790517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
13800517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
138120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
138220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
138320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
138420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1385738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            size_t max_size;
138649110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            err = mLastTrack->sampleTable->getMaxSampleSize(&max_size);
138749110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber
138849110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            if (err != OK) {
138949110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber                return err;
139049110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            }
1391738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber
139205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (max_size != 0) {
139305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // Assume that a given buffer only contains at most 10 chunks,
139405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // each chunk originally prefixed with a 2 byte length will
139505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
139605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // and thus will grow by 2 bytes per chunk.
139705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
139805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            } else {
139905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // No size was specified. Pick a conservatively large size.
140005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                int32_t width, height;
1401f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                if (!mLastTrack->meta->findInt32(kKeyWidth, &width) ||
1402f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    !mLastTrack->meta->findInt32(kKeyHeight, &height)) {
140305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ALOGE("No width or height, assuming worst case 1080p");
1404f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    width = 1920;
1405f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    height = 1080;
140605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
1407f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar
14084256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen                const char *mime;
14094256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1410f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
1411f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // AVC requires compression ratio of at least 2, and uses
1412f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // macroblocks
1413f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    max_size = ((width + 15) / 16) * ((height + 15) / 16) * 192;
1414f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                } else {
1415f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // For all other formats there is no minimum compression
1416f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // ratio. Use compression ratio of 1.
1417f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    max_size = width * height * 3 / 2;
141805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
1419f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size);
142005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
1421113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong
14224256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            // NOTE: setting another piece of metadata invalidates any pointers (such as the
14234256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            // mimetype) previously obtained, so don't cache them.
1424113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            const char *mime;
1425113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1426113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            // Calculate average frame rate.
1427113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            if (!strncasecmp("video/", mime, 6)) {
1428113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                size_t nSamples = mLastTrack->sampleTable->countSamples();
1429113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                int64_t durationUs;
1430113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                if (mLastTrack->meta->findInt64(kKeyDuration, &durationUs)) {
1431113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                    if (durationUs > 0) {
1432113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                        int32_t frameRate = (nSamples * 1000000LL +
1433113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                                    (durationUs >> 1)) / durationUs;
1434113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                        mLastTrack->meta->setInt32(kKeyFrameRate, frameRate);
1435113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                    }
1436113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                }
1437113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            }
1438113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong
143920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
144020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
144120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
144220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 't', 's'):
144320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
14440517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
14450517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
144620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
144720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setTimeToSampleParams(
144820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
144920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
145020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
145120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
145220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
145320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
145420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
145520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
145620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14574931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        case FOURCC('c', 't', 't', 's'):
14584931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        {
14590517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
14600517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
14614931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            status_t err =
14624931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                mLastTrack->sampleTable->setCompositionTimeToSampleParams(
14634931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                        data_offset, chunk_data_size);
14644931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
14654931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            if (err != OK) {
14664931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                return err;
14674931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            }
14684931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
14694931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            break;
14704931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        }
14714931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
147220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 's'):
147320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
14740517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
14750517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
147620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
147720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSyncSampleParams(
147820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
147920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
148020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
148120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
148220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
148320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
148420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
148520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
148620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14874948818cb91176df74c972ac27b2f392b5d148bcJames Dong        // @xyz
14884948818cb91176df74c972ac27b2f392b5d148bcJames Dong        case FOURCC('\xA9', 'x', 'y', 'z'):
14894948818cb91176df74c972ac27b2f392b5d148bcJames Dong        {
14900517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
14910517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
14924948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Best case the total data length inside "@xyz" box
14934948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // would be 8, for instance "@xyz" + "\x00\x04\x15\xc7" + "0+0/",
14944948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // where "\x00\x04" is the text string length with value = 4,
14954948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // "\0x15\xc7" is the language code = en, and "0+0" is a
14964948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // location (string) value with longitude = 0 and latitude = 0.
14974948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (chunk_data_size < 8) {
14984948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_MALFORMED;
14994948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
15004948818cb91176df74c972ac27b2f392b5d148bcJames Dong
15014948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Worst case the location string length would be 18,
15024948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // for instance +90.0000-180.0000, without the trailing "/" and
15034948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // the string length + language code.
15044948818cb91176df74c972ac27b2f392b5d148bcJames Dong            char buffer[18];
15054948818cb91176df74c972ac27b2f392b5d148bcJames Dong
15064948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Substracting 5 from the data size is because the text string length +
15074948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // language code takes 4 bytes, and the trailing slash "/" takes 1 byte.
15084948818cb91176df74c972ac27b2f392b5d148bcJames Dong            off64_t location_length = chunk_data_size - 5;
15094948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (location_length >= (off64_t) sizeof(buffer)) {
15104948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_MALFORMED;
15114948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
15124948818cb91176df74c972ac27b2f392b5d148bcJames Dong
15134948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (mDataSource->readAt(
15144948818cb91176df74c972ac27b2f392b5d148bcJames Dong                        data_offset + 4, buffer, location_length) < location_length) {
15154948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_IO;
15164948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
15174948818cb91176df74c972ac27b2f392b5d148bcJames Dong
15184948818cb91176df74c972ac27b2f392b5d148bcJames Dong            buffer[location_length] = '\0';
15194948818cb91176df74c972ac27b2f392b5d148bcJames Dong            mFileMetaData->setCString(kKeyLocation, buffer);
15204948818cb91176df74c972ac27b2f392b5d148bcJames Dong            break;
15214948818cb91176df74c972ac27b2f392b5d148bcJames Dong        }
15224948818cb91176df74c972ac27b2f392b5d148bcJames Dong
152320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('e', 's', 'd', 's'):
152420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
15250517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
15260517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
152720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
152820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
152920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
153020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
153120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[256];
1532c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size > (off64_t)sizeof(buffer)) {
153320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
153420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
153520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
153634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
153720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
153820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
153920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
154020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
154120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
154220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
154320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
154420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
154520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
154620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
154720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
154820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1549ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            if (mPath.size() >= 2
1550ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
1551ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // Information from the ESDS must be relied on for proper
1552ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // setup of sample rate and channel count for MPEG4 Audio.
1553ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // The generic header appears to only contain generic
1554ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // information...
1555ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1556ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio(
1557ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                        &buffer[4], chunk_data_size - 4);
1558ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1559ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                if (err != OK) {
1560ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    return err;
1561ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                }
1562ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            }
1563ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
156420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
156520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
156620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
156720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', 'C'):
156820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
15690517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
15700517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1571d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson            sp<ABuffer> buffer = new ABuffer(chunk_data_size);
157220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
157334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
1574d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson                        data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
157520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
157620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
157720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
157820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
1579d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson                    kKeyAVCC, kTypeAVCC, buffer->data(), chunk_data_size);
158020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
158120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
158220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
158320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1584244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        case FOURCC('d', '2', '6', '3'):
1585244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        {
15860517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
158717e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            /*
158817e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * d263 contains a fixed 7 bytes part:
158917e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   vendor - 4 bytes
159017e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   version - 1 byte
159117e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   level - 1 byte
159217e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   profile - 1 byte
159317e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * optionally, "d263" box itself may contain a 16-byte
159417e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * bit rate box (bitr)
159517e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   average bit rate - 4 bytes
159617e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   max bit rate - 4 bytes
159717e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             */
159817e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            char buffer[23];
159917e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            if (chunk_data_size != 7 &&
160017e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong                chunk_data_size != 23) {
160129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Incorrect D263 box size %lld", chunk_data_size);
1602244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                return ERROR_MALFORMED;
1603244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            }
1604244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1605244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            if (mDataSource->readAt(
1606244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                    data_offset, buffer, chunk_data_size) < chunk_data_size) {
1607244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                return ERROR_IO;
1608244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            }
1609244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1610244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size);
1611244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1612244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            break;
1613244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        }
1614244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
161572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'e', 't', 'a'):
161672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
161772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            uint8_t buffer[4];
1618c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size < (off64_t)sizeof(buffer)) {
16190517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen                *offset += chunk_size;
1620bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1621bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
1622bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
162372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
162472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, buffer, 4) < 4) {
16250517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen                *offset += chunk_size;
162672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
162772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
162872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
162972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (U32_AT(buffer) != 0) {
163072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                // Should be version 0, flags 0.
1631ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
1632ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // If it's not, let's assume this is one of those
1633ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // apparently malformed chunks that don't have flags
1634ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // and completely different semantics than what's
1635ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // in the MPEG4 specs and skip it.
1636ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                *offset += chunk_size;
1637ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                return OK;
163872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
163972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1640c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
164172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset = data_offset + sizeof(buffer);
164272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            while (*offset < stop_offset) {
164372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                status_t err = parseChunk(offset, depth + 1);
164472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
164572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
164672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
164772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
1648bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1649bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1650bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1651bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
165272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
165372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
165472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
16555d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('m', 'e', 'a', 'n'):
16565d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('n', 'a', 'm', 'e'):
165772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('d', 'a', 't', 'a'):
165872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
16590517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
16600517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
166172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mPath.size() == 6 && underMetaDataPath(mPath)) {
1662fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                status_t err = parseITunesMetaData(data_offset, chunk_data_size);
166372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
166472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
166572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
166672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
166772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
166872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
166972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
167072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
167172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
167272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'v', 'h', 'd'):
167372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
16740517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
16750517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1676fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            if (chunk_data_size < 24) {
167772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_MALFORMED;
167872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
167972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1680fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            uint8_t header[24];
168172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
168272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, header, sizeof(header))
168372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    < (ssize_t)sizeof(header)) {
168472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
168572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
168672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1687fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            uint64_t creationTime;
168872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (header[0] == 1) {
168972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U64_AT(&header[4]);
1690fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                mHeaderTimescale = U32_AT(&header[20]);
1691bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (header[0] != 0) {
1692bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
169372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            } else {
169472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U32_AT(&header[4]);
1695fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                mHeaderTimescale = U32_AT(&header[12]);
169672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
169772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
169872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            String8 s;
169972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            convertTimeToDate(creationTime, &s);
170072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
170172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(kKeyDate, s.string());
170272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
170372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
170472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
170572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1706dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        case FOURCC('m', 'd', 'a', 't'):
1707dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        {
1708ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("mdat chunk, drm: %d", mIsDrm);
1709dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (!mIsDrm) {
1710dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                *offset += chunk_size;
1711dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                break;
1712dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
1713dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
1714dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (chunk_size < 8) {
1715dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
1716dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
1717dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
1718dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return parseDrmSINF(offset, data_offset);
1719dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
1720dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
17213b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        case FOURCC('h', 'd', 'l', 'r'):
17223b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        {
17230517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
17240517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
17253b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t buffer;
17263b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (mDataSource->readAt(
17273b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                        data_offset + 8, &buffer, 4) < 4) {
17283b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_IO;
17293b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17303b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17313b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type = ntohl(buffer);
17323b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            // For the 3GPP file format, the handler-type within the 'hdlr' box
1733e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            // shall be 'text'. We also want to support 'sbtl' handler type
1734e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            // for a practical reason as various MPEG4 containers use it.
1735e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            if (type == FOURCC('t', 'e', 'x', 't') || type == FOURCC('s', 'b', 't', 'l')) {
17363b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
17373b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17383b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17393b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            break;
17403b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        }
17413b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17427a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        case FOURCC('t', 'x', '3', 'g'):
17437a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        {
17443b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type;
17453b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            const void *data;
17463b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            size_t size = 0;
17473b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (!mLastTrack->meta->findData(
17483b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    kKeyTextFormatData, &type, &data, &size)) {
17493b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                size = 0;
17503b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17513b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17523b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint8_t *buffer = new uint8_t[size + chunk_size];
17533b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17543b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (size > 0) {
17553b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                memcpy(buffer, data, size);
17563b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17573b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17583b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size))
17593b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    < chunk_size) {
17603b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                delete[] buffer;
17613b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                buffer = NULL;
17623b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17630517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen                // advance read pointer so we don't end up reading this again
17640517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen                *offset += chunk_size;
17653b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_IO;
17663b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17673b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17683b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            mLastTrack->meta->setData(
17693b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    kKeyTextFormatData, 0, buffer, size + chunk_size);
17703b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17713b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            delete[] buffer;
17727a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
17737a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            *offset += chunk_size;
17747a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            break;
17757a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        }
17767a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
1777515e855eae78aa495da58356486aaa666cb57fd1James Dong        case FOURCC('c', 'o', 'v', 'r'):
1778515e855eae78aa495da58356486aaa666cb57fd1James Dong        {
17790517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
17800517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1781515e855eae78aa495da58356486aaa666cb57fd1James Dong            if (mFileMetaData != NULL) {
17823856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("chunk_data_size = %lld and data_offset = %lld",
1783515e855eae78aa495da58356486aaa666cb57fd1James Dong                        chunk_data_size, data_offset);
17841552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1);
1785515e855eae78aa495da58356486aaa666cb57fd1James Dong                if (mDataSource->readAt(
17861552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                    data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) {
1787515e855eae78aa495da58356486aaa666cb57fd1James Dong                    return ERROR_IO;
1788515e855eae78aa495da58356486aaa666cb57fd1James Dong                }
1789515e855eae78aa495da58356486aaa666cb57fd1James Dong                const int kSkipBytesOfDataBox = 16;
1790515e855eae78aa495da58356486aaa666cb57fd1James Dong                mFileMetaData->setData(
1791515e855eae78aa495da58356486aaa666cb57fd1James Dong                    kKeyAlbumArt, MetaData::TYPE_NONE,
17921552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                    buffer->data() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox);
1793515e855eae78aa495da58356486aaa666cb57fd1James Dong            }
1794515e855eae78aa495da58356486aaa666cb57fd1James Dong
1795515e855eae78aa495da58356486aaa666cb57fd1James Dong            break;
1796515e855eae78aa495da58356486aaa666cb57fd1James Dong        }
1797515e855eae78aa495da58356486aaa666cb57fd1James Dong
1798fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('t', 'i', 't', 'l'):
1799fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('p', 'e', 'r', 'f'):
1800fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'u', 't', 'h'):
1801fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('g', 'n', 'r', 'e'):
1802fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'l', 'b', 'm'):
1803fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('y', 'r', 'r', 'c'):
1804fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
18050517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
18060517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1807fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            status_t err = parse3GPPMetaData(data_offset, chunk_data_size, depth);
1808fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
1809fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (err != OK) {
1810fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                return err;
1811fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
1812fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
1813fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
1814fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
1815fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
1816328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        case FOURCC('I', 'D', '3', '2'):
1817328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        {
18180517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
18190517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1820328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            if (chunk_data_size < 6) {
1821328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                return ERROR_MALFORMED;
1822328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            }
1823328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
1824328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            parseID3v2MetaData(data_offset + 6);
1825328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
1826328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            break;
1827328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        }
1828328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
18295d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('-', '-', '-', '-'):
18305d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        {
18315d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentMean.clear();
18325d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentName.clear();
18335d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentData.clear();
18345d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            *offset += chunk_size;
18355d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            break;
18365d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        }
18375d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen
183805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('s', 'i', 'd', 'x'):
183905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        {
184005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            parseSegmentIndex(data_offset, chunk_data_size);
184105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset += chunk_size;
184205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return UNKNOWN_ERROR; // stop parsing after sidx
184305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
184405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
184520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
184620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
184720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
184820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
184920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
185020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
185120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
185220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
185320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
185420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
185505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) {
185605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen  ALOGV("MPEG4Extractor::parseSegmentIndex");
185705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
185805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 12) {
185905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      return -EINVAL;
186005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
186105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
186205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
186305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) {
186405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
186505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
186605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
186705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t version = flags >> 24;
186805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    flags &= 0xffffff;
186905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
187005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx version %d", version);
187105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
187205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t referenceId;
187305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, &referenceId)) {
187405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
187505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
187605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
187705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t timeScale;
187805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 8, &timeScale)) {
187905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
188005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
188105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx refid/timescale: %d/%d", referenceId, timeScale);
188205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
188305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t earliestPresentationTime;
188405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t firstOffset;
188505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
188605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 12;
188705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 12;
188805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
188905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (version == 0) {
189005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 8) {
189105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
189205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
189305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t tmp;
189405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
189505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
189605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
189705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        earliestPresentationTime = tmp;
189805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset + 4, &tmp)) {
189905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
190005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
190105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        firstOffset = tmp;
190205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 8;
190305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 8;
190405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
190505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 16) {
190605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
190705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
190805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset, &earliestPresentationTime)) {
190905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
191005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
191105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset + 8, &firstOffset)) {
191205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
191305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
191405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 16;
191505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 16;
191605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
191705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx pres/off: %Ld/%Ld", earliestPresentationTime, firstOffset);
191805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
191905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 4) {
192005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
192105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
192205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
192305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint16_t referenceCount;
192405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt16(offset + 2, &referenceCount)) {
192505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
192605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
192705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 4;
192805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 4;
192905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("refcount: %d", referenceCount);
193005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
193105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < referenceCount * 12) {
193205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
193305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
193405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
193505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t total_duration = 0;
193605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    for (unsigned int i = 0; i < referenceCount; i++) {
193705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t d1, d2, d3;
193805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
193905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &d1) ||     // size
194005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            !mDataSource->getUInt32(offset + 4, &d2) || // duration
194105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            !mDataSource->getUInt32(offset + 8, &d3)) { // flags
194205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
194305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
194405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
194505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (d1 & 0x80000000) {
194605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGW("sub-sidx boxes not supported yet");
194705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
194805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool sap = d3 & 0x80000000;
19493f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen        uint32_t saptype = (d3 >> 28) & 7;
19503f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen        if (!sap || (saptype != 1 && saptype != 2)) {
19513f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            // type 1 and 2 are sync samples
19523f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            ALOGW("not a stream access point, or unsupported type: %08x", d3);
195305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
195405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        total_duration += d2;
195505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 12;
195605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV(" item %d, %08x %08x %08x", i, d1, d2, d3);
195705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        SidxEntry se;
195805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        se.mSize = d1 & 0x7fffffff;
195905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        se.mDurationUs = 1000000LL * d2 / timeScale;
196005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mSidxEntries.add(se);
196105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
196205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
196305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mSidxDuration = total_duration * 1000000 / timeScale;
196405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("duration: %lld", mSidxDuration);
196505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
196605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t metaDuration;
196705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mLastTrack->meta->findInt64(kKeyDuration, &metaDuration) || metaDuration == 0) {
196805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mLastTrack->meta->setInt64(kKeyDuration, mSidxDuration);
196905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
197005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
197105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
197205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
197305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
197405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
1975ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huberstatus_t MPEG4Extractor::parseTrackHeader(
1976c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t data_offset, off64_t data_size) {
1977ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (data_size < 4) {
1978ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_MALFORMED;
1979ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1980ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1981ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint8_t version;
1982ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (mDataSource->readAt(data_offset, &version, 1) < 1) {
1983ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_IO;
1984ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1985ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1986ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    size_t dynSize = (version == 1) ? 36 : 24;
1987ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1988ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint8_t buffer[36 + 60];
1989ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1990c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    if (data_size != (off64_t)dynSize + 60) {
1991ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_MALFORMED;
1992ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1993ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1994ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (mDataSource->readAt(
1995ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber                data_offset, buffer, data_size) < (ssize_t)data_size) {
1996ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_IO;
1997ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1998ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1999ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint64_t ctime, mtime, duration;
2000ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t id;
2001ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2002ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (version == 1) {
2003ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        ctime = U64_AT(&buffer[4]);
2004ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mtime = U64_AT(&buffer[12]);
2005ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        id = U32_AT(&buffer[20]);
2006ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        duration = U64_AT(&buffer[28]);
200704022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen    } else if (version == 0) {
2008ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        ctime = U32_AT(&buffer[4]);
2009ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mtime = U32_AT(&buffer[8]);
2010ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        id = U32_AT(&buffer[12]);
2011ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        duration = U32_AT(&buffer[20]);
201204022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen    } else {
201304022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen        return ERROR_UNSUPPORTED;
2014ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2015ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2016ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    mLastTrack->meta->setInt32(kKeyTrackID, id);
2017ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2018ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    size_t matrixOffset = dynSize + 16;
2019ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a00 = U32_AT(&buffer[matrixOffset]);
2020ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a01 = U32_AT(&buffer[matrixOffset + 4]);
2021ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t dx = U32_AT(&buffer[matrixOffset + 8]);
2022ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a10 = U32_AT(&buffer[matrixOffset + 12]);
2023ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a11 = U32_AT(&buffer[matrixOffset + 16]);
2024ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t dy = U32_AT(&buffer[matrixOffset + 20]);
2025ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2026ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#if 0
2027df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("x' = %.2f * x + %.2f * y + %.2f",
2028ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber         a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f);
2029df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("y' = %.2f * x + %.2f * y + %.2f",
2030ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber         a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f);
2031ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#endif
2032ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2033ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t rotationDegrees;
2034ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2035ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    static const int32_t kFixedOne = 0x10000;
2036ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) {
2037ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        // Identity, no rotation
2038ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 0;
2039ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) {
2040ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 90;
2041ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) {
2042ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 270;
2043ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) {
2044ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 180;
2045ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else {
20465ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("We only support 0,90,180,270 degree rotation matrices");
2047ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 0;
2048ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2049ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2050ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (rotationDegrees != 0) {
2051ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees);
2052ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2053ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2054b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    // Handle presentation display size, which could be different
2055b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    // from the image size indicated by kKeyWidth and kKeyHeight.
2056ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t width = U32_AT(&buffer[dynSize + 52]);
2057ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t height = U32_AT(&buffer[dynSize + 56]);
2058b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    mLastTrack->meta->setInt32(kKeyDisplayWidth, width >> 16);
2059b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    mLastTrack->meta->setInt32(kKeyDisplayHeight, height >> 16);
2060ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2061ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    return OK;
2062ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber}
2063ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2064fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhéstatus_t MPEG4Extractor::parseITunesMetaData(off64_t offset, size_t size) {
206572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (size < 4) {
206672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_MALFORMED;
206772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
206872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
206972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint8_t *buffer = new uint8_t[size + 1];
207072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (mDataSource->readAt(
207172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                offset, buffer, size) != (ssize_t)size) {
207272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        delete[] buffer;
207372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        buffer = NULL;
207472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
207572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_IO;
207672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
207772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
207872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t flags = U32_AT(buffer);
207972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
208072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t metadataKey = 0;
20815d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    char chunk[5];
20825d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    MakeFourCCString(mPath[4], chunk);
20835d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    ALOGV("meta: %s @ %lld", chunk, offset);
208472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    switch (mPath[4]) {
208572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'a', 'l', 'b'):
208672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
208772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbum;
208872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
208972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
209072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'A', 'R', 'T'):
209172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
209272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyArtist;
209372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
209472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
209566ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        case FOURCC('a', 'A', 'R', 'T'):
209666ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        {
209766ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            metadataKey = kKeyAlbumArtist;
209866ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            break;
209966ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        }
210072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'd', 'a', 'y'):
210172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
210272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyYear;
210372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
210472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
210572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'n', 'a', 'm'):
210672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
210772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyTitle;
210872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
210972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
211072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'w', 'r', 't'):
211172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
211272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyWriter;
211372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
211472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
211572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('c', 'o', 'v', 'r'):
211672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
211772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbumArt;
211872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
211972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
212072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('g', 'n', 'r', 'e'):
212172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
212272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyGenre;
212372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
212472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
212526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC(0xa9, 'g', 'e', 'n'):
212626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
212726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            metadataKey = kKeyGenre;
212826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
212926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
213011f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        case FOURCC('c', 'p', 'i', 'l'):
213111f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        {
213211f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            if (size == 9 && flags == 21) {
213311f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                char tmp[16];
213411f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                sprintf(tmp, "%d",
213511f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                        (int)buffer[size - 1]);
213611f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen
213711f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                mFileMetaData->setCString(kKeyCompilation, tmp);
213811f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            }
213911f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            break;
214011f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        }
214172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('t', 'r', 'k', 'n'):
214272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
214372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (size == 16 && flags == 0) {
214472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char tmp[16];
2145afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTrack = (uint16_t*)&buffer[10];
2146afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTotalTracks = (uint16_t*)&buffer[12];
2147afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                sprintf(tmp, "%d/%d", ntohs(*pTrack), ntohs(*pTotalTracks));
214872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
214972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
215072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
215172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
215272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
215326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC('d', 'i', 's', 'k'):
215426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
2155afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik            if ((size == 14 || size == 16) && flags == 0) {
215626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                char tmp[16];
2157afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pDisc = (uint16_t*)&buffer[10];
2158afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTotalDiscs = (uint16_t*)&buffer[12];
2159afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                sprintf(tmp, "%d/%d", ntohs(*pDisc), ntohs(*pTotalDiscs));
216026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
216126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(kKeyDiscNumber, tmp);
216226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            }
216326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
216426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
21655d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('-', '-', '-', '-'):
21665d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        {
21675d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            buffer[size] = '\0';
21685d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            switch (mPath[5]) {
21695d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('m', 'e', 'a', 'n'):
21705d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentMean.setTo((const char *)buffer + 4);
21715d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
21725d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('n', 'a', 'm', 'e'):
21735d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentName.setTo((const char *)buffer + 4);
21745d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
21755d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('d', 'a', 't', 'a'):
21765d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentData.setTo((const char *)buffer + 8);
21775d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
21785d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            }
21798c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
21808c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // Once we have a set of mean/name/data info, go ahead and process
21818c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // it to see if its something we are interested in.  Whether or not
21828c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // were are interested in the specific tag, make sure to clear out
21838c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // the set so we can be ready to process another tuple should one
21848c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // show up later in the file.
21858c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            if ((mLastCommentMean.length() != 0) &&
21868c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                (mLastCommentName.length() != 0) &&
21878c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                (mLastCommentData.length() != 0)) {
21888c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
21898c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                if (mLastCommentMean == "com.apple.iTunes"
21908c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        && mLastCommentName == "iTunSMPB") {
21918c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    int32_t delay, padding;
21928c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    if (sscanf(mLastCommentData,
21938c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                               " %*x %x %x %*x", &delay, &padding) == 2) {
21948c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
21958c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        mLastTrack->meta->setInt32(kKeyEncoderPadding, padding);
21968c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    }
21975d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                }
21988c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
21995d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentMean.clear();
22005d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentName.clear();
22015d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentData.clear();
22025d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            }
22035d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            break;
22045d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        }
220526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
220672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        default:
220772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
220872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
220972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
2210328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    if (size >= 8 && metadataKey && !mFileMetaData->hasData(metadataKey)) {
221172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        if (metadataKey == kKeyAlbumArt) {
221272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setData(
221372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    kKeyAlbumArt, MetaData::TYPE_NONE,
221472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    buffer + 8, size - 8);
221572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else if (metadataKey == kKeyGenre) {
221672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (flags == 0) {
221726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // uint8_t genre code, iTunes genre codes are
221826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // the standard id3 codes, except they start
221926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // at 1 instead of 0 (e.g. Pop is 14, not 13)
222026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // We use standard id3 numbering, so subtract 1.
222126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                int genrecode = (int)buffer[size - 1];
222226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                genrecode--;
222326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                if (genrecode < 0) {
222426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                    genrecode = 255; // reserved for 'unknown genre'
222526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                }
222672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char genre[10];
222726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                sprintf(genre, "%d", genrecode);
222872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
222972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(metadataKey, genre);
223026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            } else if (flags == 1) {
223126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // custom genre string
223226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                buffer[size] = '\0';
223326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
223426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(
223526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                        metadataKey, (const char *)buffer + 8);
223672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
223772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else {
223872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            buffer[size] = '\0';
223972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
224072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(
224172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    metadataKey, (const char *)buffer + 8);
224272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
224372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
224472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
224572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    delete[] buffer;
224672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    buffer = NULL;
224772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
224872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return OK;
224972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
225072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
2251fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhéstatus_t MPEG4Extractor::parse3GPPMetaData(off64_t offset, size_t size, int depth) {
2252fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    if (size < 4) {
2253fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        return ERROR_MALFORMED;
2254fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2255fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2256fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    uint8_t *buffer = new uint8_t[size];
2257fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    if (mDataSource->readAt(
2258fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                offset, buffer, size) != (ssize_t)size) {
2259fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        delete[] buffer;
2260fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        buffer = NULL;
2261fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2262fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        return ERROR_IO;
2263fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2264fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2265fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    uint32_t metadataKey = 0;
2266fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    switch (mPath[depth]) {
2267fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('t', 'i', 't', 'l'):
2268fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2269fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyTitle;
2270fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2271fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2272fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('p', 'e', 'r', 'f'):
2273fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2274fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyArtist;
2275fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2276fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2277fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'u', 't', 'h'):
2278fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2279fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyWriter;
2280fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2281fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2282fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('g', 'n', 'r', 'e'):
2283fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2284fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyGenre;
2285fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2286fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2287fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'l', 'b', 'm'):
2288fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2289fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (buffer[size - 1] != '\0') {
2290fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé              char tmp[4];
2291fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé              sprintf(tmp, "%u", buffer[size - 1]);
2292fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2293fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé              mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
2294fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2295fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2296fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyAlbum;
2297fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2298fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2299fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('y', 'r', 'r', 'c'):
2300fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2301fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            char tmp[5];
2302fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            uint16_t year = U16_AT(&buffer[4]);
2303fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2304fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (year < 10000) {
2305fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                sprintf(tmp, "%u", year);
2306fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2307fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                mFileMetaData->setCString(kKeyYear, tmp);
2308fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2309fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2310fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2311fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2312fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        default:
2313fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2314fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2315fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2316fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    if (metadataKey > 0) {
2317fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        bool isUTF8 = true; // Common case
2318fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        char16_t *framedata = NULL;
2319fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        int len16 = 0; // Number of UTF-16 characters
2320fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2321fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        // smallest possible valid UTF-16 string w BOM: 0xfe 0xff 0x00 0x00
2322fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        if (size - 6 >= 4) {
2323fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            len16 = ((size - 6) / 2) - 1; // don't include 0x0000 terminator
2324fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            framedata = (char16_t *)(buffer + 6);
2325fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (0xfffe == *framedata) {
2326fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                // endianness marker (BOM) doesn't match host endianness
2327fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                for (int i = 0; i < len16; i++) {
2328fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                    framedata[i] = bswap_16(framedata[i]);
2329fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                }
2330fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                // BOM is now swapped to 0xfeff, we will execute next block too
2331fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2332fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2333fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (0xfeff == *framedata) {
2334fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                // Remove the BOM
2335fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                framedata++;
2336fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                len16--;
2337fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                isUTF8 = false;
2338fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2339fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // else normal non-zero-length UTF-8 string
2340fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // we can't handle UTF-16 without BOM as there is no other
2341fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // indication of encoding.
2342fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2343fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2344fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        if (isUTF8) {
2345fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            mFileMetaData->setCString(metadataKey, (const char *)buffer + 6);
2346fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        } else {
2347fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // Convert from UTF-16 string to UTF-8 string.
2348fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            String8 tmpUTF8str(framedata, len16);
2349fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            mFileMetaData->setCString(metadataKey, tmpUTF8str.string());
2350fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2351fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2352fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2353fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    delete[] buffer;
2354fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    buffer = NULL;
2355fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2356fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    return OK;
2357fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé}
2358fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2359328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhévoid MPEG4Extractor::parseID3v2MetaData(off64_t offset) {
2360328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    ID3 id3(mDataSource, true /* ignorev1 */, offset);
2361328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2362328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    if (id3.isValid()) {
2363328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        struct Map {
2364328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            int key;
2365328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            const char *tag1;
2366328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            const char *tag2;
2367328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        };
2368328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        static const Map kMap[] = {
2369328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyAlbum, "TALB", "TAL" },
2370328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyArtist, "TPE1", "TP1" },
2371328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyAlbumArtist, "TPE2", "TP2" },
2372328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyComposer, "TCOM", "TCM" },
2373328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyGenre, "TCON", "TCO" },
2374328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyTitle, "TIT2", "TT2" },
2375328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyYear, "TYE", "TYER" },
2376328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyAuthor, "TXT", "TEXT" },
2377328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyCDTrackNumber, "TRK", "TRCK" },
2378328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyDiscNumber, "TPA", "TPOS" },
2379328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyCompilation, "TCP", "TCMP" },
2380328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        };
2381328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
2382328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2383328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        for (size_t i = 0; i < kNumMapEntries; ++i) {
2384328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            if (!mFileMetaData->hasData(kMap[i].key)) {
2385328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                ID3::Iterator *it = new ID3::Iterator(id3, kMap[i].tag1);
2386328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                if (it->done()) {
2387328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    delete it;
2388328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    it = new ID3::Iterator(id3, kMap[i].tag2);
2389328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                }
2390328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2391328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                if (it->done()) {
2392328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    delete it;
2393328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    continue;
2394328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                }
2395328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2396328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                String8 s;
2397328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                it->getString(&s);
2398328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                delete it;
2399328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2400328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                mFileMetaData->setCString(kMap[i].key, s);
2401328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            }
2402328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        }
2403328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2404328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        size_t dataSize;
2405328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        String8 mime;
2406328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        const void *data = id3.getAlbumArt(&dataSize, &mime);
2407328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2408328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        if (data) {
2409328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            mFileMetaData->setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize);
2410328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            mFileMetaData->setCString(kKeyAlbumArtMIME, mime.string());
2411328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        }
2412328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    }
2413328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé}
2414328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2415693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
241620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
241720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
2418693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return NULL;
241920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
242020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
242120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
242220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
242320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
2424693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber            return NULL;
242520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
242620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
242720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
242820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
242920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
243020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2431371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
2432371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
2433371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
2434371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
2435ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("getTrack called, pssh: %d", mPssh.size());
2436ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2437693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    return new MPEG4Source(
243805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            track->meta, mDataSource, track->timescale, track->sampleTable,
243905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mSidxEntries, mMoofOffset);
244020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
244120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2442bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber// static
2443bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) {
2444bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const char *mime;
2445bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    CHECK(track->meta->findCString(kKeyMIMEType, &mime));
2446bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2447bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    uint32_t type;
2448bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const void *data;
2449bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    size_t size;
2450bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
2451bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyAVCC, &type, &data, &size)
2452bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeAVCC) {
2453bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
2454bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
2455bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
2456bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
2457bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyESDS, &type, &data, &size)
2458bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeESDS) {
2459bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
2460bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
2461bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    }
2462bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2463169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber    if (!track->sampleTable->isValid()) {
2464169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        // Make sure we have all the metadata we need.
2465169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        return ERROR_MALFORMED;
2466169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber    }
2467169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber
2468bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    return OK;
2469bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber}
2470bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2471f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivitypedef enum {
2472f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_NONE             = -1,
2473f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_NULL_OBJECT      = 0,
2474f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_MAIN         = 1, /**< Main profile                              */
2475f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_AAC_LC           = 2,   /**< Low Complexity object                     */
2476f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_SSR          = 3,
2477f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_LTP          = 4,
2478f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_SBR              = 5,
2479f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_SCAL         = 6,
2480f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_TWIN_VQ          = 7,
2481f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_CELP             = 8,
2482f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_HVXC             = 9,
2483f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_10          = 10, /**< (reserved)                                */
2484f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_11          = 11, /**< (reserved)                                */
2485f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_TTSI             = 12, /**< TTSI Object                               */
2486f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MAIN_SYNTH       = 13, /**< Main Synthetic object                     */
2487f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_WAV_TAB_SYNTH    = 14, /**< Wavetable Synthesis object                */
2488f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_GEN_MIDI         = 15, /**< General MIDI object                       */
2489f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ALG_SYNTH_AUD_FX = 16, /**< Algorithmic Synthesis and Audio FX object */
2490f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_AAC_LC        = 17,   /**< Error Resilient(ER) AAC Low Complexity    */
2491f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_18          = 18, /**< (reserved)                                */
2492f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_AAC_LTP       = 19, /**< Error Resilient(ER) AAC LTP object        */
2493f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_AAC_SCAL      = 20,   /**< Error Resilient(ER) AAC Scalable object   */
2494f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_TWIN_VQ       = 21, /**< Error Resilient(ER) TwinVQ object         */
2495f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_BSAC          = 22,   /**< Error Resilient(ER) BSAC object           */
2496f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_AAC_LD        = 23,   /**< Error Resilient(ER) AAC LowDelay object   */
2497f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_CELP          = 24, /**< Error Resilient(ER) CELP object           */
2498f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_HVXC          = 25, /**< Error Resilient(ER) HVXC object           */
2499f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_HILN          = 26, /**< Error Resilient(ER) HILN object           */
2500f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_PARA          = 27, /**< Error Resilient(ER) Parametric object     */
2501f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_28          = 28, /**< might become SSC                          */
2502f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_PS               = 29,   /**< PS, Parametric Stereo (includes SBR)      */
2503f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MPEGS            = 30, /**< MPEG Surround                             */
2504f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2505f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ESCAPE           = 31,   /**< Signal AOT uses more than 5 bits          */
2506f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2507f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MP3ONMP4_L1      = 32, /**< MPEG-Layer1 in mp4                        */
2508f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MP3ONMP4_L2      = 33, /**< MPEG-Layer2 in mp4                        */
2509f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MP3ONMP4_L3      = 34, /**< MPEG-Layer3 in mp4                        */
2510f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_35          = 35, /**< might become DST                          */
2511f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_36          = 36, /**< might become ALS                          */
2512f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_SLS          = 37, /**< AAC + SLS                                 */
2513f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_SLS              = 38, /**< SLS                                       */
2514f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_AAC_ELD       = 39, /**< AAC Enhanced Low Delay                    */
2515f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2516f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_USAC             = 42, /**< USAC                                      */
2517f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_SAOC             = 43, /**< SAOC                                      */
2518f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_LD_MPEGS         = 44, /**< Low Delay MPEG Surround                   */
2519f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2520f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD50           = 50,  /**< Interim AOT for Rsvd50                   */
2521f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi} AUDIO_OBJECT_TYPE;
2522f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2523ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
2524ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        const void *esds_data, size_t esds_size) {
2525ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    ESDS esds(esds_data, esds_size);
252681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
252781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    uint8_t objectTypeIndication;
252881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
252981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return ERROR_MALFORMED;
253081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
253181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
253281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (objectTypeIndication == 0xe1) {
253381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        // This isn't MPEG4 audio at all, it's QCELP 14k...
253481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
253581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return OK;
253681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
253781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
2538633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong    if (objectTypeIndication  == 0x6b) {
2539633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // The media subtype is MP3 audio
2540633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // Our software MP3 audio decoder may not be able to handle
2541633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // packetized MP3 audio; for now, lets just return ERROR_UNSUPPORTED
254229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("MP3 track in MP4/3GPP file is not supported");
2543633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        return ERROR_UNSUPPORTED;
2544633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong    }
2545633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong
2546ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    const uint8_t *csd;
2547ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    size_t csd_size;
2548ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (esds.getCodecSpecificInfo(
2549ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                (const void **)&csd, &csd_size) != OK) {
2550ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
2551ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2552ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2553ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#if 0
2554ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    printf("ESD of size %d\n", csd_size);
2555ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    hexdump(csd, csd_size);
2556ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#endif
2557ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2558a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    if (csd_size == 0) {
2559a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // There's no further information, i.e. no codec specific data
2560a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // Let's assume that the information provided in the mpeg4 headers
2561a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // is accurate and hope for the best.
2562a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
2563a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        return OK;
2564a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    }
2565a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
2566ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (csd_size < 2) {
2567ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
2568ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2569ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
257000307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent    static uint32_t kSamplingRate[] = {
257100307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
257200307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        16000, 12000, 11025, 8000, 7350
257300307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent    };
257400307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent
2575aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    ABitReader br(csd, csd_size);
2576aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    uint32_t objectType = br.getBits(5);
2577ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2578aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    if (objectType == 31) {  // AAC-ELD => additional 6 bits
2579aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        objectType = 32 + br.getBits(6);
2580ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2581ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2582db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent    //keep AOT type
2583db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent    mLastTrack->meta->setInt32(kKeyAACAOT, objectType);
2584db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent
2585aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    uint32_t freqIndex = br.getBits(4);
2586aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
2587ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t sampleRate = 0;
2588ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t numChannels = 0;
2589ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (freqIndex == 15) {
2590ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        if (csd_size < 5) {
2591ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            return ERROR_MALFORMED;
2592ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
2593aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        sampleRate = br.getBits(24);
2594aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        numChannels = br.getBits(4);
2595ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    } else {
2596595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen        numChannels = br.getBits(4);
259700307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent
259800307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        if (freqIndex == 13 || freqIndex == 14) {
259900307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            return ERROR_MALFORMED;
2600ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
2601ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
260200307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        sampleRate = kSamplingRate[freqIndex];
260300307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent    }
2604595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen
2605f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    if (objectType == AOT_SBR || objectType == AOT_PS) {//SBR specific config per 14496-3 table 1.13
260600307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        uint32_t extFreqIndex = br.getBits(4);
260700307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        int32_t extSampleRate;
260800307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        if (extFreqIndex == 15) {
260900307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            if (csd_size < 8) {
2610595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen                return ERROR_MALFORMED;
2611595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen            }
261200307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            extSampleRate = br.getBits(24);
261300307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        } else {
261400307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            if (extFreqIndex == 13 || extFreqIndex == 14) {
261500307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent                return ERROR_MALFORMED;
261600307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            }
261700307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            extSampleRate = kSamplingRate[extFreqIndex];
2618595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen        }
261900307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        //TODO: save the extension sampling rate value in meta data =>
262000307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        //      mLastTrack->meta->setInt32(kKeyExtSampleRate, extSampleRate);
2621ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2622ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2623f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    switch (numChannels) {
2624f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        // values defined in 14496-3_2009 amendment-4 Table 1.19 - Channel Configuration
2625f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 0:
2626f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 1:// FC
2627f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 2:// FL FR
2628f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 3:// FC, FL FR
2629f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 4:// FC, FL FR, RC
2630f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 5:// FC, FL FR, SL SR
2631f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 6:// FC, FL FR, SL SR, LFE
2632f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            //numChannels already contains the right value
2633f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            break;
2634f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 11:// FC, FL FR, SL SR, RC, LFE
2635f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            numChannels = 7;
2636f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            break;
2637f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 7: // FC, FCL FCR, FL FR, SL SR, LFE
2638f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 12:// FC, FL  FR,  SL SR, RL RR, LFE
2639f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 14:// FC, FL  FR,  SL SR, LFE, FHL FHR
2640f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            numChannels = 8;
2641f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            break;
2642f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        default:
2643f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            return ERROR_UNSUPPORTED;
2644f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    }
2645f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2646f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    {
2647f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        if (objectType == AOT_SBR || objectType == AOT_PS) {
2648f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            const int32_t extensionSamplingFrequency = br.getBits(4);
2649f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            objectType = br.getBits(5);
2650f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2651f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            if (objectType == AOT_ESCAPE) {
2652f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                objectType = 32 + br.getBits(6);
2653f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            }
2654f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        }
2655f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        if (objectType == AOT_AAC_LC || objectType == AOT_ER_AAC_LC ||
2656f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                objectType == AOT_ER_AAC_LD || objectType == AOT_ER_AAC_SCAL ||
2657f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                objectType == AOT_ER_BSAC) {
2658f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            const int32_t frameLengthFlag = br.getBits(1);
2659f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2660f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            const int32_t dependsOnCoreCoder = br.getBits(1);
2661f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2662f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            if (dependsOnCoreCoder ) {
2663f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t coreCoderDelay = br.getBits(14);
2664f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            }
2665f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2666f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            const int32_t extensionFlag = br.getBits(1);
2667f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2668f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            if (numChannels == 0 ) {
2669f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                int32_t channelsEffectiveNum = 0;
2670f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                int32_t channelsNum = 0;
2671f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t ElementInstanceTag = br.getBits(4);
2672f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t Profile = br.getBits(2);
2673f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t SamplingFrequencyIndex = br.getBits(4);
2674f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumFrontChannelElements = br.getBits(4);
2675f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumSideChannelElements = br.getBits(4);
2676f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumBackChannelElements = br.getBits(4);
2677f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumLfeChannelElements = br.getBits(2);
2678f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumAssocDataElements = br.getBits(3);
2679f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumValidCcElements = br.getBits(4);
2680f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2681f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t MonoMixdownPresent = br.getBits(1);
2682f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                if (MonoMixdownPresent != 0) {
2683f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t MonoMixdownElementNumber = br.getBits(4);
2684f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2685f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2686f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t StereoMixdownPresent = br.getBits(1);
2687f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                if (StereoMixdownPresent != 0) {
2688f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t StereoMixdownElementNumber = br.getBits(4);
2689f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2690f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2691f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t MatrixMixdownIndexPresent = br.getBits(1);
2692f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                if (MatrixMixdownIndexPresent != 0) {
2693f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t MatrixMixdownIndex = br.getBits(2);
2694f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t PseudoSurroundEnable = br.getBits(1);
2695f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2696f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2697f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                int i;
2698f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumFrontChannelElements; i++) {
2699f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t FrontElementIsCpe = br.getBits(1);
2700f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t FrontElementTagSelect = br.getBits(4);
2701f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += FrontElementIsCpe ? 2 : 1;
2702f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2703f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2704f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumSideChannelElements; i++) {
2705f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t SideElementIsCpe = br.getBits(1);
2706f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t SideElementTagSelect = br.getBits(4);
2707f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += SideElementIsCpe ? 2 : 1;
2708f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2709f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2710f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumBackChannelElements; i++) {
2711f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t BackElementIsCpe = br.getBits(1);
2712f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t BackElementTagSelect = br.getBits(4);
2713f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += BackElementIsCpe ? 2 : 1;
2714f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2715f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                channelsEffectiveNum = channelsNum;
2716f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2717f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumLfeChannelElements; i++) {
2718f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t LfeElementTagSelect = br.getBits(4);
2719f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += 1;
2720f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2721f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                ALOGV("mpeg4 audio channelsNum = %d", channelsNum);
2722f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                ALOGV("mpeg4 audio channelsEffectiveNum = %d", channelsEffectiveNum);
2723f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                numChannels = channelsNum;
2724f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            }
2725f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        }
2726f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    }
2727f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2728ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (numChannels == 0) {
2729ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_UNSUPPORTED;
2730ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2731ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2732ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevSampleRate;
2733ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
2734ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2735ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevSampleRate != sampleRate) {
27363856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("mpeg4 audio sample rate different from previous setting. "
2737ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevSampleRate, sampleRate);
2738ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2739ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2740ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
2741ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2742ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevChannelCount;
2743ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
2744ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2745ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevChannelCount != numChannels) {
27463856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("mpeg4 audio channel count different from previous setting. "
2747ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevChannelCount, numChannels);
2748ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2749ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2750ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
2751ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2752ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    return OK;
2753ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber}
2754ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
275520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
275620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
275720111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::MPEG4Source(
275820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        const sp<MetaData> &format,
2759693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &dataSource,
276048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        int32_t timeScale,
276105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const sp<SampleTable> &sampleTable,
276205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        Vector<SidxEntry> &sidx,
276305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t firstMoofOffset)
276420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mFormat(format),
276520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDataSource(dataSource),
276648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber      mTimescale(timeScale),
276720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSampleTable(sampleTable),
276820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCurrentSampleIndex(0),
276905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentFragmentIndex(0),
277005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mSegments(sidx),
277105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mFirstMoofOffset(firstMoofOffset),
277205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentMoofOffset(firstMoofOffset),
277305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentTime(0),
2774ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoAllocSize(0),
2775ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoSizes(NULL),
2776ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoOffsetsAllocSize(0),
2777ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoOffsets(NULL),
277820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mIsAVC(false),
27796064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber      mNALLengthSize(0),
278020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mStarted(false),
278120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mGroup(NULL),
278220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mBuffer(NULL),
2783dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber      mWantsNALFragments(false),
27840024245e134467d120b40099da16c467dc365e76Andreas Huber      mSrcBuffer(NULL) {
2785ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2786ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mFormat->findInt32(kKeyCryptoMode, &mCryptoMode);
278748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    mDefaultIVSize = 0;
2788ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mFormat->findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize);
2789ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t keytype;
2790ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    const void *key;
2791ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    size_t keysize;
2792ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mFormat->findData(kKeyCryptoKey, &keytype, &key, &keysize)) {
2793ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        CHECK(keysize <= 16);
2794ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memset(mCryptoKey, 0, 16);
2795ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memcpy(mCryptoKey, key, keysize);
2796ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2797ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
279820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
279920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mFormat->findCString(kKeyMIMEType, &mime);
2800dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(success);
280120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
280218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber    mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
28036064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
28046064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    if (mIsAVC) {
28056064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        uint32_t type;
28066064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const void *data;
28076064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t size;
28086064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(format->findData(kKeyAVCC, &type, &data, &size));
28096064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
28106064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const uint8_t *ptr = (const uint8_t *)data;
28116064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
28126064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(size >= 7);
2813ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
28146064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
28156064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        // The number of bytes used to encode the length of a NAL unit.
28166064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        mNALLengthSize = 1 + (ptr[4] & 3);
28176064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
281805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
281905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    CHECK(format->findInt32(kKeyTrackID, &mTrackId));
282005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
282105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mFirstMoofOffset != 0) {
282205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t offset = mFirstMoofOffset;
282305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        parseChunk(&offset);
282405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
282520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
282620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
282720111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::~MPEG4Source() {
282820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mStarted) {
282920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        stop();
283020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
2831ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    free(mCurrentSampleInfoSizes);
2832ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    free(mCurrentSampleInfoOffsets);
283320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
283420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
283520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::start(MetaData *params) {
28367b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
28377b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
2838dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(!mStarted);
283920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
284020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t val;
2841dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (params && params->findInt32(kKeyWantsNALFragments, &val)
284220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        && val != 0) {
2843dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = true;
284420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    } else {
2845dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = false;
284620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
284720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
284820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = new MediaBufferGroup;
284920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2850738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    int32_t max_size;
2851738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
285220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2853738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    mGroup->add_buffer(new MediaBuffer(max_size));
28540024245e134467d120b40099da16c467dc365e76Andreas Huber
28550024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = new uint8_t[max_size];
285620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
285720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = true;
285820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
285920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
286020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
286120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
286220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::stop() {
28637b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
28647b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
2865dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
286620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
286720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mBuffer != NULL) {
286820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->release();
286920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
287020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
287120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28720024245e134467d120b40099da16c467dc365e76Andreas Huber    delete[] mSrcBuffer;
28730024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = NULL;
28740024245e134467d120b40099da16c467dc365e76Andreas Huber
287520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    delete mGroup;
287620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = NULL;
287720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
287820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = false;
287920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mCurrentSampleIndex = 0;
288020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
288120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
288220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
288320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
288405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseChunk(off64_t *offset) {
288505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t hdr[2];
288605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
288705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_IO;
288805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
288905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t chunk_size = ntohl(hdr[0]);
289005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t chunk_type = ntohl(hdr[1]);
289105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t data_offset = *offset + 8;
289205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
289305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (chunk_size == 1) {
289405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
289505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_IO;
289605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
289705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        chunk_size = ntoh64(chunk_size);
289805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        data_offset += 8;
289905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
290005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (chunk_size < 16) {
290105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            // The smallest valid chunk is 16 bytes long in this case.
290205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
290305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
290405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (chunk_size < 8) {
290505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // The smallest valid chunk is 8 bytes long.
290605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
290705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
290805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
290905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    char chunk[5];
291005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    MakeFourCCString(chunk_type, chunk);
291105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Source chunk %s @ %llx", chunk, *offset);
291205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
291305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t chunk_data_size = *offset + chunk_size - data_offset;
291405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
291505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    switch(chunk_type) {
291605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
291705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'r', 'a', 'f'):
291805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('m', 'o', 'o', 'f'): {
291905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t stop_offset = *offset + chunk_size;
292005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset = data_offset;
292105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            while (*offset < stop_offset) {
292205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err = parseChunk(offset);
292305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (err != OK) {
292405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return err;
292505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
292605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
292705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
29283f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                // *offset points to the box following this moof. Find the next moof from there.
29293f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen
29303f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                while (true) {
29313f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
29323f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                        return ERROR_END_OF_STREAM;
29333f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    }
29343f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    chunk_size = ntohl(hdr[0]);
29353f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    chunk_type = ntohl(hdr[1]);
29363f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
29373f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                        mNextMoofOffset = *offset;
29383f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                        break;
29393f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    }
29403f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    *offset += chunk_size;
29413f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                }
294205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
294305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
294405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
294505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
294605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'f', 'h', 'd'): {
294705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err;
294805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if ((err = parseTrackFragmentHeader(data_offset, chunk_data_size)) != OK) {
294905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return err;
295005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
295105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                *offset += chunk_size;
295205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                break;
295305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
295405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
295505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'r', 'u', 'n'): {
295605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err;
295705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (mLastParsedTrackId == mTrackId) {
295805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    if ((err = parseTrackFragmentRun(data_offset, chunk_data_size)) != OK) {
295905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        return err;
296005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    }
296105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
296205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
296305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                *offset += chunk_size;
296405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                break;
296505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
296605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2967ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'a', 'i', 'z'): {
2968ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            status_t err;
2969ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((err = parseSampleAuxiliaryInformationSizes(data_offset, chunk_data_size)) != OK) {
2970ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return err;
2971ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
2972ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
2973ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
2974ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2975ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'a', 'i', 'o'): {
2976ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            status_t err;
2977ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((err = parseSampleAuxiliaryInformationOffsets(data_offset, chunk_data_size)) != OK) {
2978ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return err;
2979ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
2980ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
2981ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
2982ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2983ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2984ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('m', 'd', 'a', 't'): {
2985ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // parse DRM info if present
2986ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("MPEG4Source::parseChunk mdat");
2987ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // if saiz/saoi was previously observed, do something with the sampleinfos
2988ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
2989ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
2990ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2991ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
299205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        default: {
299305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset += chunk_size;
299405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
299505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
299605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
299705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
299805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
299905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
300084333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG4Source::parseSampleAuxiliaryInformationSizes(
300184333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        off64_t offset, off64_t /* size */) {
3002ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("parseSampleAuxiliaryInformationSizes");
3003ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // 14496-12 8.7.12
3004ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t version;
3005ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(
3006ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset, &version, sizeof(version))
3007ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            < (ssize_t)sizeof(version)) {
3008ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3009ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3010ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3011ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (version != 0) {
3012ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_UNSUPPORTED;
3013ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3014ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
3015ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3016ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t flags;
3017ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt24(offset, &flags)) {
3018ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3019ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3020ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 3;
3021ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3022ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (flags & 1) {
3023ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        uint32_t tmp;
3024ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
3025ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_MALFORMED;
3026ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3027ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentAuxInfoType = tmp;
3028ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        offset += 4;
3029ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
3030ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_MALFORMED;
3031ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3032ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentAuxInfoTypeParameter = tmp;
3033ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        offset += 4;
3034ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3035ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3036ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t defsize;
3037ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(offset, &defsize, 1) != 1) {
3038ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_MALFORMED;
3039ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3040ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mCurrentDefaultSampleInfoSize = defsize;
3041ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
3042ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3043ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t smplcnt;
3044ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &smplcnt)) {
3045ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_MALFORMED;
3046ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
304748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    mCurrentSampleInfoCount = smplcnt;
3048ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 4;
3049ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
305048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (mCurrentDefaultSampleInfoSize != 0) {
305148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        ALOGV("@@@@ using default sample info size of %d", mCurrentDefaultSampleInfoSize);
305248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return OK;
305348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
3054ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (smplcnt > mCurrentSampleInfoAllocSize) {
3055ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoSizes = (uint8_t*) realloc(mCurrentSampleInfoSizes, smplcnt);
3056ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoAllocSize = smplcnt;
3057ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3058ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3059ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mDataSource->readAt(offset, mCurrentSampleInfoSizes, smplcnt);
3060ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    return OK;
3061ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen}
3062ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
306384333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(
306484333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        off64_t offset, off64_t /* size */) {
3065ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("parseSampleAuxiliaryInformationOffsets");
3066ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // 14496-12 8.7.13
3067ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t version;
3068ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(offset, &version, sizeof(version)) != 1) {
3069ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3070ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3071ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
3072ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3073ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t flags;
3074ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt24(offset, &flags)) {
3075ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3076ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3077ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 3;
3078ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3079ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t entrycount;
3080ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &entrycount)) {
3081ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3082ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3083ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 4;
3084ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3085ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (entrycount > mCurrentSampleInfoOffsetsAllocSize) {
3086ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoOffsets = (uint64_t*) realloc(mCurrentSampleInfoOffsets, entrycount * 8);
3087ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoOffsetsAllocSize = entrycount;
3088ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3089ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mCurrentSampleInfoOffsetCount = entrycount;
3090ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3091ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < entrycount; i++) {
3092ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (version == 0) {
3093ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t tmp;
3094ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (!mDataSource->getUInt32(offset, &tmp)) {
3095ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
3096ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3097ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mCurrentSampleInfoOffsets[i] = tmp;
3098ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset += 4;
3099ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        } else {
3100ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint64_t tmp;
3101ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (!mDataSource->getUInt64(offset, &tmp)) {
3102ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
3103ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3104ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mCurrentSampleInfoOffsets[i] = tmp;
3105ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset += 8;
3106ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3107ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3108ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3109ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // parse clear/encrypted data
3110ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3111ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    off64_t drmoffset = mCurrentSampleInfoOffsets[0]; // from moof
3112ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3113ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    drmoffset += mCurrentMoofOffset;
3114ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int ivlength;
3115ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    CHECK(mFormat->findInt32(kKeyCryptoDefaultIVSize, &ivlength));
311648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
311748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    // read CencSampleAuxiliaryDataFormats
3118ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mCurrentSampleInfoCount; i++) {
3119ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Sample *smpl = &mCurrentSamples.editItemAt(i);
3120ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3121ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memset(smpl->iv, 0, 16);
3122ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (mDataSource->readAt(drmoffset, smpl->iv, ivlength) != ivlength) {
3123ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_IO;
3124ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3125ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3126ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        drmoffset += ivlength;
3127ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
312848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        int32_t smplinfosize = mCurrentDefaultSampleInfoSize;
312948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        if (smplinfosize == 0) {
313048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smplinfosize = mCurrentSampleInfoSizes[i];
3131ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
313248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        if (smplinfosize > ivlength) {
313348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint16_t numsubsamples;
313448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (!mDataSource->getUInt16(drmoffset, &numsubsamples)) {
3135ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
3136ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3137ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            drmoffset += 2;
313848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            for (size_t j = 0; j < numsubsamples; j++) {
313948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                uint16_t numclear;
314048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                uint32_t numencrypted;
314148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                if (!mDataSource->getUInt16(drmoffset, &numclear)) {
314248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                    return ERROR_IO;
314348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                }
314448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                drmoffset += 2;
314548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                if (!mDataSource->getUInt32(drmoffset, &numencrypted)) {
314648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                    return ERROR_IO;
314748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                }
314848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                drmoffset += 4;
314948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->clearsizes.add(numclear);
315048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->encryptedsizes.add(numencrypted);
3151ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
315248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        } else {
315348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smpl->clearsizes.add(0);
315448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smpl->encryptedsizes.add(smpl->size);
3155ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3156ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3157ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3158ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3159ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    return OK;
3160ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen}
3161ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
316205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentHeader(off64_t offset, off64_t size) {
316305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
316405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 8) {
316505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
316605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
316705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
316805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
3169ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags
317005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
317105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
317205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
317305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & 0xff000000) {
317405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
317505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
317605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
317705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, (uint32_t*)&mLastParsedTrackId)) {
317805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
317905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
318005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
318105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mLastParsedTrackId != mTrackId) {
318205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // this is not the right track, skip it
318305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
318405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
318505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
318605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mFlags = flags;
318705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mTrackID = mLastParsedTrackId;
318805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 8;
318905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 8;
319005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
319105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("fragment header: %08x %08x", flags, mTrackFragmentHeaderInfo.mTrackID);
319205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
319305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent) {
319405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 8) {
319505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
319605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
319705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
319805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset, &mTrackFragmentHeaderInfo.mBaseDataOffset)) {
319905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
320005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
320105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 8;
320205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 8;
320305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
320405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
320505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent) {
320605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
320705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
320805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
320905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
321005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mSampleDescriptionIndex)) {
321105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
321205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
321305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
321405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
321505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
321605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
321705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
321805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
321905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
322005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
322105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
322205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleDuration)) {
322305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
322405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
322505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
322605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
322705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
322805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
322905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
323005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
323105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
323205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
323305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
323405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleSize)) {
323505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
323605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
323705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
323805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
323905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
324005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
324105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
324205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
324305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
324405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
324505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
324605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleFlags)) {
324705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
324805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
324905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
325005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
325105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
325205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
325305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!(flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent)) {
325405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mTrackFragmentHeaderInfo.mBaseDataOffset = mCurrentMoofOffset;
325505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
325605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
325705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mDataOffset = 0;
325805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
325905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
326005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
326105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentRun(off64_t offset, off64_t size) {
326205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
326305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Extractor::parseTrackFragmentRun");
326405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 8) {
326505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
326605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
326705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
326805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    enum {
326905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kDataOffsetPresent                  = 0x01,
327005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kFirstSampleFlagsPresent            = 0x04,
327105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleDurationPresent              = 0x100,
327205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleSizePresent                  = 0x200,
327305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleFlagsPresent                 = 0x400,
327405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleCompositionTimeOffsetPresent = 0x800,
327505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
327605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
327705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
327805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) {
327905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
328005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
328105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("fragment run flags: %08x", flags);
328205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
328305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & 0xff000000) {
328405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
328505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
328605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
328705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if ((flags & kFirstSampleFlagsPresent) && (flags & kSampleFlagsPresent)) {
328805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // These two shall not be used together.
328905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
329005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
329105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
329205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t sampleCount;
329305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, &sampleCount)) {
329405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
329505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
329605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 8;
329705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 8;
329805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
329905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t dataOffset = mTrackFragmentHeaderInfo.mDataOffset;
330005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
330105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t firstSampleFlags = 0;
330205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
330305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kDataOffsetPresent) {
330405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
330505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
330605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
330705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
330805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int32_t dataOffsetDelta;
330905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, (uint32_t*)&dataOffsetDelta)) {
331005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
331105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
331205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
331305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        dataOffset = mTrackFragmentHeaderInfo.mBaseDataOffset + dataOffsetDelta;
331405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
331505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
331605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
331705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
331805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
331905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kFirstSampleFlagsPresent) {
332005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
332105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
332205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
332305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
332405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &firstSampleFlags)) {
332505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
332605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
332705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
332805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
332905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
333005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
333105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t sampleDuration = 0, sampleSize = 0, sampleFlags = 0,
333205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen             sampleCtsOffset = 0;
333305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
333405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size_t bytesPerSample = 0;
333505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleDurationPresent) {
333605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
333705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
333805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
333905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration;
334005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
334105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration;
334205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
334305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
334405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleSizePresent) {
334505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
334605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
334705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
334805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
334905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
335005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
335105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
335205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
335305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleFlagsPresent) {
335405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
335505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
335605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
335705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
335805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
335905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
336005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
336105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
336205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleCompositionTimeOffsetPresent) {
336305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
336405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
336505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleCtsOffset = 0;
336605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
336705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
336805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < sampleCount * bytesPerSample) {
336905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
337005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
337105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
337205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Sample tmp;
337305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    for (uint32_t i = 0; i < sampleCount; ++i) {
337405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleDurationPresent) {
337505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleDuration)) {
337605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
337705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
337805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
337905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
338005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
338105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleSizePresent) {
338205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleSize)) {
338305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
338405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
338505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
338605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
338705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
338805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleFlagsPresent) {
338905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleFlags)) {
339005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
339105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
339205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
339305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
339405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
339505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleCompositionTimeOffsetPresent) {
339605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleCtsOffset)) {
339705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
339805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
339905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
340005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
340105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3402ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        ALOGV("adding sample %d at offset 0x%08llx, size %u, duration %u, "
3403ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen              " flags 0x%08x", i + 1,
340405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dataOffset, sampleSize, sampleDuration,
340505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                (flags & kFirstSampleFlagsPresent) && i == 0
340605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ? firstSampleFlags : sampleFlags);
340705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.offset = dataOffset;
340805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.size = sampleSize;
340905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.duration = sampleDuration;
341005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentSamples.add(tmp);
341105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
341205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        dataOffset += sampleSize;
341305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
341405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
341505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mDataOffset = dataOffset;
341605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
341705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
341805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
341905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
342020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> MPEG4Source::getFormat() {
34217b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
34227b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
342320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return mFormat;
342420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
342520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
34266064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const {
34276064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    switch (mNALLengthSize) {
34286064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 1:
34296064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return *data;
34306064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 2:
34316064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U16_AT(data);
34326064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 3:
34336064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return ((size_t)data[0] << 16) | U16_AT(&data[1]);
34346064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 4:
34356064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U32_AT(data);
34366064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
34376064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
34386064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // This cannot happen, mNALLengthSize springs to life by adding 1 to
34396064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // a 2-bit integer.
34406064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    CHECK(!"Should not be here.");
34416064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
34426064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    return 0;
34436064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber}
34446064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
344520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::read(
344620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
34477b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
34487b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
3449dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
345020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
345105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mFirstMoofOffset > 0) {
345205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return fragmentedRead(out, options);
345305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
345405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
345520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *out = NULL;
345620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3457abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    int64_t targetSampleTimeUs = -1;
3458abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
345920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t seekTimeUs;
3460abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
3461abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
3462abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t findFlags = 0;
3463abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        switch (mode) {
3464abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_PREVIOUS_SYNC:
3465abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagBefore;
3466abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3467abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_NEXT_SYNC:
3468abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagAfter;
3469abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3470abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST_SYNC:
3471abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST:
3472abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagClosest;
3473abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3474abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            default:
3475abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                CHECK(!"Should not be here.");
3476abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3477abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3478abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
347920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        uint32_t sampleIndex;
3480abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        status_t err = mSampleTable->findSampleAtTime(
348120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                seekTimeUs * mTimescale / 1000000,
3482abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                &sampleIndex, findFlags);
3483abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3484abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
3485abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // We found the closest sample already, now we want the sync
3486abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // sample preceding it (or the sample itself of course), even
3487abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // if the subsequent sync sample is closer.
3488abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            findFlags = SampleTable::kFlagBefore;
3489abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3490abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3491abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleIndex;
3492abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (err == OK) {
3493abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            err = mSampleTable->findSyncSampleNear(
3494abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    sampleIndex, &syncSampleIndex, findFlags);
3495abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
349620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3497788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        uint32_t sampleTime;
3498788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        if (err == OK) {
3499788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber            err = mSampleTable->getMetaDataForSample(
3500788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber                    sampleIndex, NULL, NULL, &sampleTime);
3501788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        }
3502788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber
350320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (err != OK) {
35045295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            if (err == ERROR_OUT_OF_RANGE) {
35055295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // An attempt to seek past the end of the stream would
35065295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // normally cause this ERROR_OUT_OF_RANGE error. Propagating
35075295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // this all the way to the MediaPlayer would cause abnormal
35085295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // termination. Legacy behaviour appears to be to behave as if
35095295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // we had seeked to the end of stream, ending normally.
35105295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                err = ERROR_END_OF_STREAM;
35115295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            }
351205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("end of stream");
351320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return err;
351420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
351520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3516abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
3517abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
3518abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3519abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3520abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#if 0
3521abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleTime;
3522abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
3523abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    syncSampleIndex, NULL, NULL, &syncSampleTime));
3524abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3525df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("seek to time %lld us => sample at time %lld us, "
3526abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             "sync sample at time %lld us",
3527abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             seekTimeUs,
3528abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             sampleTime * 1000000ll / mTimescale,
3529abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             syncSampleTime * 1000000ll / mTimescale);
3530abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#endif
3531abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3532abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        mCurrentSampleIndex = syncSampleIndex;
353320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mBuffer != NULL) {
353420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
353520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
353620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
353720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
353820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // fall through
353920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
354020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3541c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset;
35420024245e134467d120b40099da16c467dc365e76Andreas Huber    size_t size;
35434678a6dc5f09008481524949a9667af5a6190374Andreas Huber    uint32_t cts;
35448bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    bool isSyncSample;
3545dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool newBuffer = false;
3546dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (mBuffer == NULL) {
3547dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        newBuffer = true;
354820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3549c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        status_t err =
3550c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber            mSampleTable->getMetaDataForSample(
35514678a6dc5f09008481524949a9667af5a6190374Andreas Huber                    mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample);
355220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3553dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
3554dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
3555dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3556dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3557dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        err = mGroup->acquire_buffer(&mBuffer);
3558c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
3559dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
3560ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            CHECK(mBuffer == NULL);
3561dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
3562dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
35630024245e134467d120b40099da16c467dc365e76Andreas Huber    }
356420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3565dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (!mIsAVC || mWantsNALFragments) {
3566dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (newBuffer) {
3567dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ssize_t num_bytes_read =
356834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
3569dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3570dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            if (num_bytes_read < (ssize_t)size) {
3571dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer->release();
3572dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer = NULL;
3573dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3574dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                return ERROR_IO;
3575dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            }
3576dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
35777b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber            CHECK(mBuffer != NULL);
3578dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->set_range(0, size);
3579dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->meta_data()->clear();
358048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mBuffer->meta_data()->setInt64(
35814678a6dc5f09008481524949a9667af5a6190374Andreas Huber                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
3582abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3583abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            if (targetSampleTimeUs >= 0) {
3584abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                mBuffer->meta_data()->setInt64(
3585abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                        kKeyTargetTime, targetSampleTimeUs);
3586abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            }
3587abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
35888bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            if (isSyncSample) {
35898bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
35908bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            }
35918bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
3592dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ++mCurrentSampleIndex;
3593dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3594dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3595dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (!mIsAVC) {
3596dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            *out = mBuffer;
3597dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
3598dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3599dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return OK;
3600dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3601dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3602dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Each NAL unit is split up into its constituent fragments and
3603dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // each one of them returned in its own buffer.
3604dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
36056064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(mBuffer->range_length() >= mNALLengthSize);
3606dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3607dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        const uint8_t *src =
3608dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
3609dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
36106064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t nal_size = parseNALSize(src);
3611e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
361229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("incomplete NAL unit.");
3613e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3614e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer->release();
3615e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer = NULL;
3616e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3617e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            return ERROR_MALFORMED;
3618e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        }
3619dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3620dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        MediaBuffer *clone = mBuffer->clone();
36217b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(clone != NULL);
36226064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
3623dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
36247b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(mBuffer != NULL);
3625dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mBuffer->set_range(
36266064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_offset() + mNALLengthSize + nal_size,
36276064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_length() - mNALLengthSize - nal_size);
3628dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3629dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (mBuffer->range_length() == 0) {
3630dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->release();
3631dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
3632dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3633dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3634dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        *out = clone;
3635dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3636dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        return OK;
3637dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    } else {
3638dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Whole NAL units are returned but each fragment is prefixed by
3639dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // the start code (0x00 00 00 01).
3640dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        ssize_t num_bytes_read = 0;
3641dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        int32_t drm = 0;
3642dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
3643dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (usesDRM) {
3644dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            num_bytes_read =
3645dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
3646dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
3647dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
3648dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
364920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
365020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (num_bytes_read < (ssize_t)size) {
365120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
365220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
365320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3654dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return ERROR_IO;
365520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
365620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3657dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (usesDRM) {
3658dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK(mBuffer != NULL);
3659dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            mBuffer->set_range(0, size);
36606064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
3661dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
3662dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            uint8_t *dstData = (uint8_t *)mBuffer->data();
3663dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size_t srcOffset = 0;
3664dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size_t dstOffset = 0;
3665e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3666dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            while (srcOffset < size) {
366734fe252c89e33572d01fea981b58d7b115e76164James Dong                bool isMalFormed = (srcOffset + mNALLengthSize > size);
366834fe252c89e33572d01fea981b58d7b115e76164James Dong                size_t nalLength = 0;
366934fe252c89e33572d01fea981b58d7b115e76164James Dong                if (!isMalFormed) {
367034fe252c89e33572d01fea981b58d7b115e76164James Dong                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
367134fe252c89e33572d01fea981b58d7b115e76164James Dong                    srcOffset += mNALLengthSize;
367234fe252c89e33572d01fea981b58d7b115e76164James Dong                    isMalFormed = srcOffset + nalLength > size;
367334fe252c89e33572d01fea981b58d7b115e76164James Dong                }
3674e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
367534fe252c89e33572d01fea981b58d7b115e76164James Dong                if (isMalFormed) {
367629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                    ALOGE("Video is malformed");
3677dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    mBuffer->release();
3678dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    mBuffer = NULL;
3679dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return ERROR_MALFORMED;
3680dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
3681dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
3682dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                if (nalLength == 0) {
3683dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    continue;
3684dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
3685dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3686dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                CHECK(dstOffset + 4 <= mBuffer->size());
3687dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3688dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3689dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3690dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3691dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 1;
3692dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
3693dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                srcOffset += nalLength;
3694dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstOffset += nalLength;
3695dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
3696dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK_EQ(srcOffset, size);
3697dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK(mBuffer != NULL);
3698dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            mBuffer->set_range(0, dstOffset);
3699dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3700dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
370120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->meta_data()->clear();
370248c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        mBuffer->meta_data()->setInt64(
37034678a6dc5f09008481524949a9667af5a6190374Andreas Huber                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
3704abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3705abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (targetSampleTimeUs >= 0) {
3706abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            mBuffer->meta_data()->setInt64(
3707abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    kKeyTargetTime, targetSampleTimeUs);
3708abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3709abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
37108bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        if (isSyncSample) {
37118bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
37128bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        }
37138bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
371420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        ++mCurrentSampleIndex;
371520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
371620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        *out = mBuffer;
371720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
371820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
371920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
372020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
372120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
372220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
372305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::fragmentedRead(
372405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MediaBuffer **out, const ReadOptions *options) {
372505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
372605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Source::fragmentedRead");
372705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
372805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    CHECK(mStarted);
372905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
373005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    *out = NULL;
373105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
373205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t targetSampleTimeUs = -1;
373305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
373405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t seekTimeUs;
373505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ReadOptions::SeekMode mode;
373605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
373705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
373805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int numSidxEntries = mSegments.size();
373905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (numSidxEntries != 0) {
374005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            int64_t totalTime = 0;
374105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t totalOffset = mFirstMoofOffset;
374205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            for (int i = 0; i < numSidxEntries; i++) {
374305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                const SidxEntry *se = &mSegments[i];
374405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (totalTime + se->mDurationUs > seekTimeUs) {
374505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    // The requested time is somewhere in this segment
37463f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    if ((mode == ReadOptions::SEEK_NEXT_SYNC && seekTimeUs > totalTime) ||
374705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        (mode == ReadOptions::SEEK_CLOSEST_SYNC &&
374805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        (seekTimeUs - totalTime) > (totalTime + se->mDurationUs - seekTimeUs))) {
374905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        // requested next sync, or closest sync and it was closer to the end of
375005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        // this segment
375105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        totalTime += se->mDurationUs;
375205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        totalOffset += se->mSize;
375305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    }
375405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    break;
375505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
375605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                totalTime += se->mDurationUs;
375705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                totalOffset += se->mSize;
375805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
3759ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentMoofOffset = totalOffset;
3760ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSamples.clear();
3761ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSampleIndex = 0;
3762ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            parseChunk(&totalOffset);
3763ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentTime = totalTime * mTimescale / 1000000ll;
3764ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen        } else {
3765ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            // without sidx boxes, we can only seek to 0
3766ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentMoofOffset = mFirstMoofOffset;
3767ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSamples.clear();
3768ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSampleIndex = 0;
3769ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            off64_t tmp = mCurrentMoofOffset;
3770ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            parseChunk(&tmp);
3771ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentTime = 0;
377205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
377305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
377405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer != NULL) {
377505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
377605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
377705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
377805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
377905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // fall through
378005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
378105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
378205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t offset = 0;
3783442cc6dc48f8188e097617f7f804c314a9dacd0eAndreas Huber    size_t size = 0;
378405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t cts = 0;
378505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    bool isSyncSample = false;
378605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    bool newBuffer = false;
378705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mBuffer == NULL) {
378805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        newBuffer = true;
378905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
379005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mCurrentSampleIndex >= mCurrentSamples.size()) {
37913f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            // move to next fragment if there is one
37923f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            if (mNextMoofOffset <= mCurrentMoofOffset) {
37933f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                return ERROR_END_OF_STREAM;
37943f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            }
3795ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            off64_t nextMoof = mNextMoofOffset;
379605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentMoofOffset = nextMoof;
379705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentSamples.clear();
379805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentSampleIndex = 0;
379905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            parseChunk(&nextMoof);
3800ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            if (mCurrentSampleIndex >= mCurrentSamples.size()) {
3801ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen                return ERROR_END_OF_STREAM;
3802ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            }
380305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
380405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
380505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
380605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset = smpl->offset;
380705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size = smpl->size;
380805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        cts = mCurrentTime;
380905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentTime += smpl->duration;
381005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        isSyncSample = (mCurrentSampleIndex == 0); // XXX
381105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
381205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        status_t err = mGroup->acquire_buffer(&mBuffer);
381305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
381405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (err != OK) {
381505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer == NULL);
381605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("acquire_buffer returned %d", err);
381705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return err;
381805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
381905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
382005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
382148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
382248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    const sp<MetaData> bufmeta = mBuffer->meta_data();
382348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    bufmeta->clear();
382448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (smpl->encryptedsizes.size()) {
382548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // store clear/encrypted lengths in metadata
382648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyPlainSizes, 0,
382748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->clearsizes.array(), smpl->clearsizes.size() * 4);
382848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyEncryptedSizes, 0,
382948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
383048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
383148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
383248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setInt32(kKeyCryptoMode, mCryptoMode);
383348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16);
383448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
383548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
383605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mIsAVC || mWantsNALFragments) {
383705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (newBuffer) {
383805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ssize_t num_bytes_read =
383905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
384005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
384105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (num_bytes_read < (ssize_t)size) {
384205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->release();
384305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer = NULL;
384405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
384505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                ALOGV("i/o error");
384605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_IO;
384705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
384805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
384905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
385005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, size);
385105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt64(
385205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
385305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
385405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (targetSampleTimeUs >= 0) {
385505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->meta_data()->setInt64(
385605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        kKeyTargetTime, targetSampleTimeUs);
385705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
385805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
385905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (isSyncSample) {
386005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
386105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
386205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
386305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ++mCurrentSampleIndex;
386405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
386505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
386605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mIsAVC) {
386705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *out = mBuffer;
386805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
386905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
387005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return OK;
387105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
387205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
387305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // Each NAL unit is split up into its constituent fragments and
387405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // each one of them returned in its own buffer.
387505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
387605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(mBuffer->range_length() >= mNALLengthSize);
387705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
387805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const uint8_t *src =
387905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
388005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
388105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size_t nal_size = parseNALSize(src);
388205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
388305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGE("incomplete NAL unit.");
388405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
388505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
388605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
388705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
388805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
388905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
389005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
389105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MediaBuffer *clone = mBuffer->clone();
389205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(clone != NULL);
389305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
389405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
389505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(mBuffer != NULL);
389605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer->set_range(
389705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->range_offset() + mNALLengthSize + nal_size,
389805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->range_length() - mNALLengthSize - nal_size);
389905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
390005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer->range_length() == 0) {
390105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
390205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
390305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
390405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
390505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        *out = clone;
390605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
390705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
390805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
390905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV("whole NAL");
391005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // Whole NAL units are returned but each fragment is prefixed by
391105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // the start code (0x00 00 00 01).
391205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ssize_t num_bytes_read = 0;
391305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int32_t drm = 0;
391405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
391505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (usesDRM) {
391605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            num_bytes_read =
391705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
391805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else {
391905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
392005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
392105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
392205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (num_bytes_read < (ssize_t)size) {
392305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
392405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
392505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
392605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("i/o error");
392705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_IO;
392805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
392905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
393005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (usesDRM) {
393105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
393205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, size);
393305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
393405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else {
393505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            uint8_t *dstData = (uint8_t *)mBuffer->data();
393605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            size_t srcOffset = 0;
393705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            size_t dstOffset = 0;
393805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
393905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            while (srcOffset < size) {
394005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                bool isMalFormed = (srcOffset + mNALLengthSize > size);
394105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                size_t nalLength = 0;
394205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (!isMalFormed) {
394305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
394405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    srcOffset += mNALLengthSize;
394505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    isMalFormed = srcOffset + nalLength > size;
394605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
394705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
394805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (isMalFormed) {
394905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ALOGE("Video is malformed");
395005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    mBuffer->release();
395105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    mBuffer = NULL;
395205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return ERROR_MALFORMED;
395305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
395405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
395505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (nalLength == 0) {
395605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    continue;
395705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
395805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
395905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                CHECK(dstOffset + 4 <= mBuffer->size());
396005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
396105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
396205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
396305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
396405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 1;
396505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
396605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                srcOffset += nalLength;
396705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstOffset += nalLength;
396805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
396905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK_EQ(srcOffset, size);
397005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
397105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, dstOffset);
397205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
397305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
397405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer->meta_data()->setInt64(
397505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
397605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
397705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (targetSampleTimeUs >= 0) {
397805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt64(
397905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    kKeyTargetTime, targetSampleTimeUs);
398005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
398105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
398205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (isSyncSample) {
398305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
398405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
398505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
398605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ++mCurrentSampleIndex;
398705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
398805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        *out = mBuffer;
398905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer = NULL;
399005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
399105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
399205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
399305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
399405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3995bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas HuberMPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix(
3996bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        const char *mimePrefix) {
3997bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    for (Track *track = mFirstTrack; track != NULL; track = track->next) {
3998bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        const char *mime;
3999bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        if (track->meta != NULL
4000bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                && track->meta->findCString(kKeyMIMEType, &mime)
4001bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) {
4002bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber            return track;
4003bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        }
4004bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    }
4005bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber
4006bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    return NULL;
4007bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber}
4008bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber
40091b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool LegacySniffMPEG4(
4010693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
401120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[8];
401220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
401334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    ssize_t n = source->readAt(4, header, sizeof(header));
401420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (n < (ssize_t)sizeof(header)) {
401520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return false;
401620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
401720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
401820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
4019b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8)
4020b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8)
40210dba73763a04d39faf999dcc5ef12af3c99535a7Andreas Huber        || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
4022ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
4023983b449a27b5fa91eca82ede5204b4341899be62Andreas Huber        || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
402418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
40255a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        *confidence = 0.4;
402620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
402720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return true;
402820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
402920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
403020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return false;
403120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
403220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
40331b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool isCompatibleBrand(uint32_t fourcc) {
40341b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    static const uint32_t kCompatibleBrands[] = {
40351b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', 'm'),
40361b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', '2'),
40371b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('a', 'v', 'c', '1'),
40381b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('3', 'g', 'p', '4'),
40391b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '1'),
40401b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '2'),
40414cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong
40424cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        // Won't promise that the following file types can be played.
40434cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        // Just give these file types a chance.
40444cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        FOURCC('q', 't', ' ', ' '),  // Apple's QuickTime
40454cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        FOURCC('M', 'S', 'N', 'V'),  // Sony's PSP
404658fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber
404758fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber        FOURCC('3', 'g', '2', 'a'),  // 3GPP2
404858fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber        FOURCC('3', 'g', '2', 'b'),
40491b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    };
40501b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
40511b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    for (size_t i = 0;
40521b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]);
40531b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         ++i) {
40541b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        if (kCompatibleBrands[i] == fourcc) {
40551b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            return true;
40561b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
40571b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
40581b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
40591b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
40601b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
40611b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
40621b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// Attempt to actually parse the 'ftyp' atom and determine if a suitable
40631b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// compatible brand is present.
4064a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// Also try to identify where this file's metadata ends
4065a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// (end of the 'moov' atom) and report it to the caller as part of
4066a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// the metadata.
40671b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool BetterSniffMPEG4(
4068a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
4069a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        sp<AMessage> *meta) {
4070a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    // We scan up to 128 bytes to identify this file as an MP4.
4071a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    static const off64_t kMaxScanOffset = 128ll;
40721b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4073a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    off64_t offset = 0ll;
4074a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    bool foundGoodFileType = false;
4075a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    off64_t moovAtomEndOffset = -1ll;
4076a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    bool done = false;
40771b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4078a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    while (!done && offset < kMaxScanOffset) {
4079a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint32_t hdr[2];
4080a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        if (source->readAt(offset, hdr, 8) < 8) {
4081a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            return false;
4082a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        }
4083a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4084a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint64_t chunkSize = ntohl(hdr[0]);
4085a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint32_t chunkType = ntohl(hdr[1]);
4086a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        off64_t chunkDataOffset = offset + 8;
4087a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4088a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        if (chunkSize == 1) {
4089a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            if (source->readAt(offset + 8, &chunkSize, 8) < 8) {
40901b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                return false;
40911b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
40921b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4093a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            chunkSize = ntoh64(chunkSize);
4094a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            chunkDataOffset += 8;
4095a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4096a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            if (chunkSize < 16) {
4097a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                // The smallest valid chunk is 16 bytes long in this case.
4098a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                return false;
4099a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            }
4100a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        } else if (chunkSize < 8) {
4101a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            // The smallest valid chunk is 8 bytes long.
4102a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            return false;
4103a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        }
4104a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4105a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        off64_t chunkDataSize = offset + chunkSize - chunkDataOffset;
4106a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
410705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        char chunkstring[5];
410805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MakeFourCCString(chunkType, chunkstring);
410905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV("saw chunk type %s, size %lld @ %lld", chunkstring, chunkSize, offset);
4110a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        switch (chunkType) {
4111a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            case FOURCC('f', 't', 'y', 'p'):
4112a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            {
4113a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                if (chunkDataSize < 8) {
4114a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    return false;
4115a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
4116a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4117a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4;
4118a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
4119a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (i == 1) {
4120a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        // Skip this index, it refers to the minorVersion,
4121a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        // not a brand.
4122a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        continue;
4123a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
4124a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4125a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    uint32_t brand;
4126a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (source->readAt(
4127a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                                chunkDataOffset + 4 * i, &brand, 4) < 4) {
4128a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        return false;
4129a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
4130a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4131a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    brand = ntohl(brand);
4132a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4133a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (isCompatibleBrand(brand)) {
4134a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        foundGoodFileType = true;
4135a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        break;
4136a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
4137a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
4138a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4139a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                if (!foundGoodFileType) {
4140a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    return false;
4141a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
4142a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
41431b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                break;
41441b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
4145a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4146a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            case FOURCC('m', 'o', 'o', 'v'):
4147a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            {
4148a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                moovAtomEndOffset = offset + chunkSize;
4149a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4150a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                done = true;
4151a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                break;
4152a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            }
4153a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4154a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            default:
4155a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                break;
41561b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
4157a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4158a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        offset += chunkSize;
41591b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
41601b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4161a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (!foundGoodFileType) {
41621b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return false;
41631b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
41641b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
41651b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
41665a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber    *confidence = 0.4f;
41671b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4168a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (moovAtomEndOffset >= 0) {
4169a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        *meta = new AMessage;
4170a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        (*meta)->setInt64("meta-data-size", moovAtomEndOffset);
4171a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4172456caf3f5f0af673dc120c17c23635f40d8f5ac2Andreas Huber        ALOGV("found metadata size: %lld", moovAtomEndOffset);
4173a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    }
4174a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
41751b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return true;
41761b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
41771b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
41781b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberbool SniffMPEG4(
41795a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
4180a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        sp<AMessage> *meta) {
4181a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (BetterSniffMPEG4(source, mimeType, confidence, meta)) {
41821b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
41831b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
41841b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
41851b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    if (LegacySniffMPEG4(source, mimeType, confidence)) {
41865ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Identified supported mpeg4 through LegacySniffMPEG4.");
41871b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
41881b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
41891b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
41901b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
41911b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
41921b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
419320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
4194