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"
1989e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber
2020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <ctype.h>
21a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <inttypes.h>
2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <stdint.h>
2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <stdlib.h>
2420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <string.h>
2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <utils/Log.h>
27a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn
28a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include "include/MPEG4Extractor.h"
29a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include "include/SampleTable.h"
30a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include "include/ESDS.h"
31a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn
32aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke#include <media/stagefright/foundation/ABitReader.h>
33d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson#include <media/stagefright/foundation/ABuffer.h>
34ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#include <media/stagefright/foundation/ADebug.h>
35a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber#include <media/stagefright/foundation/AMessage.h>
3620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
3720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBufferGroup.h>
3818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/String8.h>
4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé#include <byteswap.h>
44328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé#include "include/ID3.h"
45fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
4620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
4720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Source : public MediaSource {
4920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Caller retains ownership of both "dataSource" and "sampleTable".
51942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    MPEG4Source(const sp<MPEG4Extractor> &owner,
52942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen                const sp<MetaData> &format,
53693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber                const sp<DataSource> &dataSource,
5448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                int32_t timeScale,
5505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                const sp<SampleTable> &sampleTable,
5605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                Vector<SidxEntry> &sidx,
57c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                const Trex *trex,
5805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                off64_t firstMoofOffset);
5920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t start(MetaData *params = NULL);
6120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t stop();
6220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual sp<MetaData> getFormat();
6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL);
6605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    virtual status_t fragmentedRead(MediaBuffer **buffer, const ReadOptions *options = NULL);
6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
68693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huberprotected:
69693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    virtual ~MPEG4Source();
70693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber
7120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
727b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex mLock;
737b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
74942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    // keep the MPEG4Extractor around, since we're referencing its data
75942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    sp<MPEG4Extractor> mOwner;
7620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mFormat;
77693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<DataSource> mDataSource;
7820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t mTimescale;
79693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<SampleTable> mSampleTable;
8020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t mCurrentSampleIndex;
8105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t mCurrentFragmentIndex;
8205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Vector<SidxEntry> &mSegments;
83c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    const Trex *mTrex;
8405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mFirstMoofOffset;
8505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mCurrentMoofOffset;
8605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mNextMoofOffset;
8705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t mCurrentTime;
8805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int32_t mLastParsedTrackId;
8905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int32_t mTrackId;
9020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
91ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int32_t mCryptoMode;    // passed in from extractor
92ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int32_t mDefaultIVSize; // passed in from extractor
93ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t mCryptoKey[16]; // passed in from extractor
94ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentAuxInfoType;
95ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentAuxInfoTypeParameter;
9648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    int32_t mCurrentDefaultSampleInfoSize;
97ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoCount;
98ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoAllocSize;
99ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t* mCurrentSampleInfoSizes;
100ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoOffsetCount;
101ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoOffsetsAllocSize;
102ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint64_t* mCurrentSampleInfoOffsets;
103ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
10420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mIsAVC;
1053b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    bool mIsHEVC;
1066064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    size_t mNALLengthSize;
1076064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
10820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mStarted;
10920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBufferGroup *mGroup;
11120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *mBuffer;
11320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
114dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool mWantsNALFragments;
11520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1160024245e134467d120b40099da16c467dc365e76Andreas Huber    uint8_t *mSrcBuffer;
1170024245e134467d120b40099da16c467dc365e76Andreas Huber
1186064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    size_t parseNALSize(const uint8_t *data) const;
11905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseChunk(off64_t *offset);
12005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseTrackFragmentHeader(off64_t offset, off64_t size);
12105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseTrackFragmentRun(off64_t offset, off64_t size);
122ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    status_t parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size);
123ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    status_t parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size);
12405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
12505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    struct TrackFragmentHeaderInfo {
12605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        enum Flags {
12705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kBaseDataOffsetPresent         = 0x01,
12805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kSampleDescriptionIndexPresent = 0x02,
12905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleDurationPresent  = 0x08,
13005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleSizePresent      = 0x10,
13105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleFlagsPresent     = 0x20,
13205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDurationIsEmpty               = 0x10000,
13305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        };
13405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
13505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mTrackID;
13605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mFlags;
13705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint64_t mBaseDataOffset;
13805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mSampleDescriptionIndex;
13905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleDuration;
14005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleSize;
14105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleFlags;
14205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
14305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint64_t mDataOffset;
14405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
14505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    TrackFragmentHeaderInfo mTrackFragmentHeaderInfo;
14605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
14705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    struct Sample {
14805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t offset;
14905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size_t size;
15005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t duration;
151c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        int32_t compositionOffset;
152ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        uint8_t iv[16];
153ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Vector<size_t> clearsizes;
154ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Vector<size_t> encryptedsizes;
15505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
15605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Vector<Sample> mCurrentSamples;
1576064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
15820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source(const MPEG4Source &);
15920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source &operator=(const MPEG4Source &);
16020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
16120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
16250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This custom data source wraps an existing one and satisfies requests
16350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// falling entirely within a cached range from the cache while forwarding
16450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// all remaining requests to the wrapped datasource.
16550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This is used to cache the full sampletable metadata for a single track,
16650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// possibly wrapping multiple times to cover all tracks, i.e.
16750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// Each MPEG4DataSource caches the sampletable metadata for a single track.
16850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
16950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstruct MPEG4DataSource : public DataSource {
17050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource(const sp<DataSource> &source);
17150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual status_t initCheck() const;
173c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
174c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    virtual status_t getSize(off64_t *size);
17550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual uint32_t flags();
17650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
177c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    status_t setCachedRange(off64_t offset, size_t size);
17850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprotected:
18050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual ~MPEG4DataSource();
18150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprivate:
18350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex mLock;
18450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    sp<DataSource> mSource;
186c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t mCachedOffset;
18750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    size_t mCachedSize;
18850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    uint8_t *mCache;
18950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    void clearCache();
19150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource(const MPEG4DataSource &);
19350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource &operator=(const MPEG4DataSource &);
19450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber};
19550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source)
19750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    : mSource(source),
19850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCachedOffset(0),
19950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCachedSize(0),
20050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCache(NULL) {
20150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
20250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
20350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::~MPEG4DataSource() {
20450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    clearCache();
20550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
20650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
20750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Hubervoid MPEG4DataSource::clearCache() {
20850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (mCache) {
20950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        free(mCache);
21050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        mCache = NULL;
21150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
21250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
21350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedOffset = 0;
21450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedSize = 0;
21550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
21650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
21750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstatus_t MPEG4DataSource::initCheck() const {
21850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->initCheck();
21950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
22050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
221c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongssize_t MPEG4DataSource::readAt(off64_t offset, void *data, size_t size) {
22250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex::Autolock autoLock(mLock);
22350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
22450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (offset >= mCachedOffset
22550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            && offset + size <= mCachedOffset + mCachedSize) {
22650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        memcpy(data, &mCache[offset - mCachedOffset], size);
22750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return size;
22850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
22950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
23050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->readAt(offset, data, size);
23150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
23250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
233c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4DataSource::getSize(off64_t *size) {
23450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->getSize(size);
23550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
23650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
23750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberuint32_t MPEG4DataSource::flags() {
23850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->flags();
23950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
24050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
241c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4DataSource::setCachedRange(off64_t offset, size_t size) {
24250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex::Autolock autoLock(mLock);
24350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
24450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    clearCache();
24550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
24650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCache = (uint8_t *)malloc(size);
24750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
24850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (mCache == NULL) {
24950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return -ENOMEM;
25050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
25150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
25250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedOffset = offset;
25350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedSize = size;
25450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
25550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    ssize_t err = mSource->readAt(mCachedOffset, mCache, mCachedSize);
25650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
25750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (err < (ssize_t)size) {
25850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        clearCache();
25950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
26050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return ERROR_IO;
26150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
26250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
26350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return OK;
26450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
26550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
26650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber////////////////////////////////////////////////////////////////////////////////
26750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
26820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatic void hexdump(const void *_data, size_t size) {
26920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const uint8_t *data = (const uint8_t *)_data;
27020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t offset = 0;
27120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (offset < size) {
272377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        printf("0x%04zx  ", offset);
27320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        size_t n = size - offset;
27520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (n > 16) {
27620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            n = 16;
27720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < 16; ++i) {
28020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (i == 8) {
28120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(" ");
28220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
28320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (offset + i < size) {
28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%02x ", data[offset + i]);
28620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("   ");
28820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
29020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf(" ");
29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < n; ++i) {
29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (isprint(data[offset + i])) {
29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%c", data[offset + i]);
29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(".");
29820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
29920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf("\n");
30220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        offset += 16;
30420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
30520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
30620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huberstatic const char *FourCC2MIME(uint32_t fourcc) {
30820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch (fourcc) {
30920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
31018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AAC;
31120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
31318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_NB;
31420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
315371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
31618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_WB;
317371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
31820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
31918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_MPEG4;
32020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
322e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('h', '2', '6', '3'):
323e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('H', '2', '6', '3'):
32418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_H263;
32520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
32718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_AVC;
32820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3293b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'v', 'c', '1'):
3303b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'e', 'v', '1'):
3313b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            return MEDIA_MIMETYPE_VIDEO_HEVC;
33220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
333dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(!"should not be here.");
33420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
33520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
33620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
33720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissenstatic bool AdjustChannelsAndRate(uint32_t fourcc, uint32_t *channels, uint32_t *rate) {
33948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, FourCC2MIME(fourcc))) {
34048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // AMR NB audio is always mono, 8kHz
34148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *channels = 1;
34248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *rate = 8000;
34348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return true;
34448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, FourCC2MIME(fourcc))) {
34548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // AMR WB audio is always mono, 16kHz
34648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *channels = 1;
34748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *rate = 16000;
34848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return true;
34948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
35048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    return false;
35148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen}
35248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
353693d271e62a3726689ff68f4505ba49228eb94b2Andreas HuberMPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
354c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    : mMoofOffset(0),
35505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mDataSource(source),
356bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber      mInitCheck(NO_INIT),
3577be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber      mHasVideo(false),
358fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen      mHeaderTimescale(0),
35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mFirstTrack(NULL),
36072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber      mLastTrack(NULL),
361dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mFileMetaData(new MetaData),
362dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mFirstSINF(NULL),
363dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mIsDrm(false) {
36420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
36520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Extractor::~MPEG4Extractor() {
36720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
36820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
36920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        Track *next = track->next;
37020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete track;
37220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = next;
37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFirstTrack = mLastTrack = NULL;
375dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
376dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    SINF *sinf = mFirstSINF;
377dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (sinf) {
378dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        SINF *next = sinf->next;
3798da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        delete[] sinf->IPMPData;
380dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        delete sinf;
381dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf = next;
382dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
383dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    mFirstSINF = NULL;
384ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
385ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mPssh.size(); i++) {
386ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        delete [] mPssh[i].data;
387ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
38820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
38920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
39005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenuint32_t MPEG4Extractor::flags() const {
39105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return CAN_PAUSE |
39205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ((mMoofOffset == 0 || mSidxEntries.size() != 0) ?
39305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    (CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK) : 0);
39405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
39505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3967be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Hubersp<MetaData> MPEG4Extractor::getMetaData() {
3977be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    status_t err;
3987be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    if ((err = readMetaData()) != OK) {
39972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return new MetaData;
4007be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    }
4017be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
40272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return mFileMetaData;
4037be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber}
4047be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
405693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersize_t MPEG4Extractor::countTracks() {
40620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
40720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
408ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        ALOGV("MPEG4Extractor::countTracks: no tracks");
409693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return 0;
41020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
41120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
412693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    size_t n = 0;
41320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
41420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
415693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        ++n;
41620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
41720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
41820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
419a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("MPEG4Extractor::countTracks: %zu tracks", n);
420693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    return n;
42120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
42220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4237e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Hubersp<MetaData> MPEG4Extractor::getTrackMetaData(
4247e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        size_t index, uint32_t flags) {
42520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
42620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
42720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return NULL;
42820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
42920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
43120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
43220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
43320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
43420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
43520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
43720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
43820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
43920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
440371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
441371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
442371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
443371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
4447e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    if ((flags & kIncludeExtensiveMetaData)
4457e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            && !track->includes_expensive_metadata) {
4467e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        track->includes_expensive_metadata = true;
4477e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
4487e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        const char *mime;
4497e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        CHECK(track->meta->findCString(kKeyMIMEType, &mime));
4507e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        if (!strncasecmp("video/", mime, 6)) {
45105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (mMoofOffset > 0) {
45205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                int64_t duration;
45305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (track->meta->findInt64(kKeyDuration, &duration)) {
45405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    // nothing fancy, just pick a frame near 1/4th of the duration
45505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    track->meta->setInt64(
45605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            kKeyThumbnailTime, duration / 4);
45705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
45805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            } else {
45905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t sampleIndex;
46005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t sampleTime;
46105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK
46205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        && track->sampleTable->getMetaDataForSample(
46305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            sampleIndex, NULL /* offset */, NULL /* size */,
46405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            &sampleTime) == OK) {
46505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    track->meta->setInt64(
46605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            kKeyThumbnailTime,
46705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            ((int64_t)sampleTime * 1000000) / track->timescale);
46805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
4697e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            }
4707e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        }
4717e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    }
4727e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
47320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return track->meta;
47420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
47520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
47648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissenstatic void MakeFourCCString(uint32_t x, char *s) {
47748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[0] = x >> 24;
47848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[1] = (x >> 16) & 0xff;
47948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[2] = (x >> 8) & 0xff;
48048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[3] = x & 0xff;
48148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[4] = '\0';
48248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen}
48348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
48420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Extractor::readMetaData() {
485bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    if (mInitCheck != NO_INIT) {
486bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        return mInitCheck;
48720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
48820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
489c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = 0;
49020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
49105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    while (true) {
492a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen        off64_t orig_offset = offset;
49305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        err = parseChunk(&offset, 0);
494a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen
4954ff2a0dbb178c4ea652f30aa4f1d3deb9fdbc832Lajos Molnar        if (err != OK && err != UNKNOWN_ERROR) {
4964ff2a0dbb178c4ea652f30aa4f1d3deb9fdbc832Lajos Molnar            break;
4974ff2a0dbb178c4ea652f30aa4f1d3deb9fdbc832Lajos Molnar        } else if (offset <= orig_offset) {
498a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            // only continue parsing if the offset was advanced,
499a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            // otherwise we might end up in an infinite loop
500a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            ALOGE("did not advance: 0x%lld->0x%lld", orig_offset, offset);
501a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            err = ERROR_MALFORMED;
502a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            break;
503a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen        } else if (err == OK) {
50405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            continue;
50505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
5064ff2a0dbb178c4ea652f30aa4f1d3deb9fdbc832Lajos Molnar
50705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t hdr[2];
50805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mDataSource->readAt(offset, hdr, 8) < 8) {
50905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
51005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
51105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t chunk_type = ntohl(hdr[1]);
5123f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen        if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
51305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            // store the offset of the first segment
51405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mMoofOffset = offset;
5153f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen        } else if (chunk_type != FOURCC('m', 'd', 'a', 't')) {
5163f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            // keep parsing until we get to the data
5173f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            continue;
51805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
51905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        break;
52020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
5217be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
522bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    if (mInitCheck == OK) {
52372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        if (mHasVideo) {
524bc8b5faec8a0a9ad7c8d94945e7b000d63f0afe6Andreas Huber            mFileMetaData->setCString(
525bc8b5faec8a0a9ad7c8d94945e7b000d63f0afe6Andreas Huber                    kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG4);
52672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else {
52772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
52872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
529bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    } else {
530bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        mInitCheck = err;
53120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
53220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
533bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    CHECK_NE(err, (status_t)NO_INIT);
534ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
535ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // copy pssh data into file metadata
536ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int psshsize = 0;
537ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mPssh.size(); i++) {
538ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        psshsize += 20 + mPssh[i].datalen;
539ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
540ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (psshsize) {
541ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        char *buf = (char*)malloc(psshsize);
542ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        char *ptr = buf;
543ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        for (size_t i = 0; i < mPssh.size(); i++) {
544ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memcpy(ptr, mPssh[i].uuid, 20); // uuid + length
545ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memcpy(ptr + 20, mPssh[i].data, mPssh[i].datalen);
546ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ptr += (20 + mPssh[i].datalen);
547ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
548ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mFileMetaData->setData(kKeyPssh, 'pssh', buf, psshsize);
549ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        free(buf);
550ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
551bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    return mInitCheck;
55220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
55320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
554dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wangchar* MPEG4Extractor::getDrmTrackInfo(size_t trackID, int *len) {
555dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mFirstSINF == NULL) {
556dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return NULL;
557dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
558dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
559dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    SINF *sinf = mFirstSINF;
560dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (sinf && (trackID != sinf->trackID)) {
561dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf = sinf->next;
562dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
563dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
564dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (sinf == NULL) {
565dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return NULL;
566dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
567dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
568dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    *len = sinf->len;
569dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return sinf->IPMPData;
570dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
571dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
572dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang// Reads an encoded integer 7 bits at a time until it encounters the high bit clear.
57356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenstatic int32_t readSize(off64_t offset,
574dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        const sp<DataSource> DataSource, uint8_t *numOfBytes) {
575dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint32_t size = 0;
576dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t data;
577dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    bool moreData = true;
578dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    *numOfBytes = 0;
579dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
580dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (moreData) {
581dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (DataSource->readAt(offset, &data, 1) < 1) {
582dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return -1;
583dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
584dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        offset ++;
585dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        moreData = (data >= 128) ? true : false;
586dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        size = (size << 7) | (data & 0x7f); // Take last 7 bits
587dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        (*numOfBytes) ++;
588dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
589dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
590dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return size;
591dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
592dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
59384333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG4Extractor::parseDrmSINF(
59484333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        off64_t * /* offset */, off64_t data_offset) {
595dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t updateIdTag;
596dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
597dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
598dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
599dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset ++;
600dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
601dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (0x01/*OBJECT_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
602dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
603dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
604dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
605dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t numOfBytes;
606dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    int32_t size = readSize(data_offset, mDataSource, &numOfBytes);
607dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size < 0) {
608dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
609dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
610dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    int32_t classSize = size;
611dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset += numOfBytes;
612dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
613dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while(size >= 11 ) {
614dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t descriptorTag;
615dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, &descriptorTag, 1) < 1) {
616dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
617dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
618dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset ++;
619dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
620dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (0x11/*OBJECT_DESCRIPTOR_ID_TAG*/ != descriptorTag) {
621dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
622dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
623dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
624dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t buffer[8];
625dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        //ObjectDescriptorID and ObjectDescriptor url flag
626dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, buffer, 2) < 2) {
627dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
628dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
629dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset += 2;
630dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
631dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if ((buffer[1] >> 5) & 0x0001) { //url flag is set
632dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
633dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
634dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
635dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, buffer, 8) < 8) {
636dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
637dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
638dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset += 8;
639dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
640dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if ((0x0F/*ES_ID_REF_TAG*/ != buffer[1])
641dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                || ( 0x0A/*IPMP_DESCRIPTOR_POINTER_ID_TAG*/ != buffer[5])) {
642dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
643dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
644dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
645dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        SINF *sinf = new SINF;
646dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->trackID = U16_AT(&buffer[3]);
647dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->IPMPDescriptorID = buffer[7];
648dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->next = mFirstSINF;
649dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        mFirstSINF = sinf;
650dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
651dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        size -= (8 + 2 + 1);
652dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
653dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
654dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size != 0) {
655dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
656dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
657dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
658dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
659dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
660dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
661dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset ++;
662dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
663dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if(0x05/*IPMP_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
664dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
665dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
666dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
667dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    size = readSize(data_offset, mDataSource, &numOfBytes);
668dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size < 0) {
669dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
670dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
671dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    classSize = size;
672dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset += numOfBytes;
673dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
674dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (size > 0) {
675dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t tag;
676dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        int32_t dataLen;
677dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, &tag, 1) < 1) {
678dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
679dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
680dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset ++;
681dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
682dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (0x0B/*IPMP_DESCRIPTOR_ID_TAG*/ == tag) {
683dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            uint8_t id;
684dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            dataLen = readSize(data_offset, mDataSource, &numOfBytes);
685dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (dataLen < 0) {
686dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
687dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            } else if (dataLen < 4) {
688dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
689dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
690dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset += numOfBytes;
691dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
692dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (mDataSource->readAt(data_offset, &id, 1) < 1) {
693dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
694dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
695dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset ++;
696dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
697dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            SINF *sinf = mFirstSINF;
698dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            while (sinf && (sinf->IPMPDescriptorID != id)) {
699dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                sinf = sinf->next;
700dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
701dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (sinf == NULL) {
702dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
703dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
704dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            sinf->len = dataLen - 3;
7058da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            sinf->IPMPData = new (std::nothrow) char[sinf->len];
7068da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            if (sinf->IPMPData == NULL) {
7078da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen                return ERROR_MALFORMED;
7088da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            }
709f7df9ab3187a3c02bffe1fba10d3fb95197e4a07Ichitaro Kohara            data_offset += 2;
710dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
711f7df9ab3187a3c02bffe1fba10d3fb95197e4a07Ichitaro Kohara            if (mDataSource->readAt(data_offset, sinf->IPMPData, sinf->len) < sinf->len) {
712dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
713dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
714dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset += sinf->len;
715dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
716dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size -= (dataLen + numOfBytes + 1);
717dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
718dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
719dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
720dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size != 0) {
721dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
722dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
723dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
724dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return UNKNOWN_ERROR;  // Return a dummy error.
725dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
726dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
72772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstruct PathAdder {
72872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder(Vector<uint32_t> *path, uint32_t chunkType)
72972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        : mPath(path) {
73072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        mPath->push(chunkType);
73172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
73272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
73372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    ~PathAdder() {
73472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        mPath->pop();
73572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
73672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
73772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberprivate:
73872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    Vector<uint32_t> *mPath;
73972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
74072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder(const PathAdder &);
74172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder &operator=(const PathAdder &);
74272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber};
74372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
74472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic bool underMetaDataPath(const Vector<uint32_t> &path) {
74572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return path.size() >= 5
74672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[0] == FOURCC('m', 'o', 'o', 'v')
74772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[1] == FOURCC('u', 'd', 't', 'a')
74872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[2] == FOURCC('m', 'e', 't', 'a')
74972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[3] == FOURCC('i', 'l', 's', 't');
75072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
75172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
75272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber// Given a time in seconds since Jan 1 1904, produce a human-readable string.
75372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic void convertTimeToDate(int64_t time_1904, String8 *s) {
75472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    time_t time_1970 = time_1904 - (((66 * 365 + 17) * 24) * 3600);
75572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
75672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    char tmp[32];
75772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", gmtime(&time_1970));
75872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
75972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    s->setTo(tmp);
76072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
76172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
762c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
7635d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    ALOGV("entering parseChunk %lld/%d", *offset, depth);
76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t hdr[2];
76534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_IO;
76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
76820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint64_t chunk_size = ntohl(hdr[0]);
76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t chunk_type = ntohl(hdr[1]);
770c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t data_offset = *offset + 8;
77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (chunk_size == 1) {
77334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
77420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_IO;
77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        chunk_size = ntoh64(chunk_size);
77720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        data_offset += 8;
77871b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber
77971b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        if (chunk_size < 16) {
78071b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber            // The smallest valid chunk is 16 bytes long in this case.
78171b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber            return ERROR_MALFORMED;
78271b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        }
783a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen    } else if (chunk_size == 0) {
784a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen        if (depth == 0) {
785a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            // atom extends to end of file
786a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            off64_t sourceSize;
787a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            if (mDataSource->getSize(&sourceSize) == OK) {
788a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen                chunk_size = (sourceSize - *offset);
789a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            } else {
790a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen                // XXX could we just pick a "sufficiently large" value here?
791a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen                ALOGE("atom size is 0, and data source has no size");
792a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen                return ERROR_MALFORMED;
793a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            }
794a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen        } else {
795a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            // not allowed for non-toplevel atoms, skip it
796a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            *offset += 4;
797a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            return OK;
798a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen        }
79971b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber    } else if (chunk_size < 8) {
80071b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        // The smallest valid chunk is 8 bytes long.
801a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGE("invalid chunk size: %" PRIu64, chunk_size);
80271b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        return ERROR_MALFORMED;
80320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
80420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
80520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    char chunk[5];
80620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MakeFourCCString(chunk_type, chunk);
80705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("chunk: %s @ %lld, %d", chunk, *offset, depth);
80820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
80920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#if 0
81020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static const char kWhitespace[] = "                                        ";
81120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
812a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    printf("%sfound chunk '%s' of size %" PRIu64 "\n", indent, chunk, chunk_size);
81320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
81420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    char buffer[256];
815ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    size_t n = chunk_size;
816ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    if (n > sizeof(buffer)) {
817ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        n = sizeof(buffer);
818ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    }
819ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    if (mDataSource->readAt(*offset, buffer, n)
820ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber            < (ssize_t)n) {
821ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        return ERROR_IO;
82220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
823ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
824ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    hexdump(buffer, n);
82520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#endif
82620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
82772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder autoAdder(&mPath, chunk_type);
82872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
829c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t chunk_data_size = *offset + chunk_size - data_offset;
83020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
83172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (chunk_type != FOURCC('c', 'p', 'r', 't')
832515e855eae78aa495da58356486aaa666cb57fd1James Dong            && chunk_type != FOURCC('c', 'o', 'v', 'r')
83372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            && mPath.size() == 5 && underMetaDataPath(mPath)) {
834c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t stop_offset = *offset + chunk_size;
83572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        *offset = data_offset;
83672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        while (*offset < stop_offset) {
83772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            status_t err = parseChunk(offset, depth + 1);
83872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (err != OK) {
83972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return err;
84072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
84172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
842bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
843bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (*offset != stop_offset) {
844bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
845bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
84672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
84772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return OK;
84872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
84972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
85020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch(chunk_type) {
85120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'v'):
85220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'k'):
85320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'i', 'a'):
85420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'i', 'n', 'f'):
85520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('d', 'i', 'n', 'f'):
85620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'b', 'l'):
85720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'v', 'e', 'x'):
85820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'f'):
85920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'f'):
86020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'f', 'r', 'a'):
86172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('u', 'd', 't', 'a'):
86272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('i', 'l', 's', 't'):
863ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'i', 'n', 'f'):
864ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'c', 'h', 'i'):
8650a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        case FOURCC('e', 'd', 't', 's'):
86620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
86750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
868a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                ALOGV("sampleTable chunk is %" PRIu64 " bytes long.", chunk_size);
86950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
870b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                if (mDataSource->flags()
871b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                        & (DataSource::kWantsPrefetching
872b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                            | DataSource::kIsCachingDataSource)) {
87350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    sp<MPEG4DataSource> cachedSource =
87450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                        new MPEG4DataSource(mDataSource);
87550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
87650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
87750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                        mDataSource = cachedSource;
87850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    }
87950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                }
8801edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber
8811edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber                mLastTrack->sampleTable = new SampleTable(mDataSource);
88250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            }
88350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
8846f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber            bool isTrack = false;
885bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (chunk_type == FOURCC('t', 'r', 'a', 'k')) {
8866f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                isTrack = true;
8876f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
888bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                Track *track = new Track;
889bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->next = NULL;
890bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                if (mLastTrack) {
891bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    mLastTrack->next = track;
892bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                } else {
893bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    mFirstTrack = track;
894bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                }
895bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                mLastTrack = track;
896bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
897bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->meta = new MetaData;
898bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->includes_expensive_metadata = false;
8996f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                track->skipTrack = false;
900bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->timescale = 0;
901bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->meta->setCString(kKeyMIMEType, "application/octet-stream");
902bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
903bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
904c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
90520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset;
90620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
90720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
90820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
90920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
91020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
91120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
91220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
913bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
914bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
915bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
916bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
9176f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber            if (isTrack) {
9186f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                if (mLastTrack->skipTrack) {
9196f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    Track *cur = mFirstTrack;
9206f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
9216f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    if (cur == mLastTrack) {
9226f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        delete cur;
9236f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        mFirstTrack = mLastTrack = NULL;
9246f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    } else {
9256f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        while (cur && cur->next != mLastTrack) {
9266f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                            cur = cur->next;
9276f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        }
9286f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        cur->next = NULL;
9296f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        delete mLastTrack;
9306f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        mLastTrack = cur;
9316f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    }
9326f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
9336f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    return OK;
9346f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                }
9356f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
936bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                status_t err = verifyTrack(mLastTrack);
937bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
938bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                if (err != OK) {
939bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    return err;
940bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                }
941bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
942bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                mInitCheck = OK;
94320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
944dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                if (!mIsDrm) {
945dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return UNKNOWN_ERROR;  // Return a dummy error.
946dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                } else {
947dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return OK;
948dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
94920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
95020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
95120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
95220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9530a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        case FOURCC('e', 'l', 's', 't'):
9540a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        {
9550517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
9560517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
9570a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            // See 14496-12 8.6.6
9580a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            uint8_t version;
9590a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (mDataSource->readAt(data_offset, &version, 1) < 1) {
9600a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                return ERROR_IO;
9610a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
9620a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9630a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            uint32_t entry_count;
9640a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (!mDataSource->getUInt32(data_offset + 4, &entry_count)) {
9650a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                return ERROR_IO;
9660a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
9670a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9680a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (entry_count != 1) {
9690a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                // we only support a single entry at the moment, for gapless playback
9700a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                ALOGW("ignoring edit list with %d entries", entry_count);
971fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            } else if (mHeaderTimescale == 0) {
972210efd48ed21ca0084d9440f9a1db7d9878f8094Marco Nelissen                ALOGW("ignoring edit list because timescale is 0");
9730a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            } else {
9740a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                off64_t entriesoffset = data_offset + 8;
9750a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                uint64_t segment_duration;
9760a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int64_t media_time;
9770a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9780a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                if (version == 1) {
9790a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    if (!mDataSource->getUInt64(entriesoffset, &segment_duration) ||
9800a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                            !mDataSource->getUInt64(entriesoffset + 8, (uint64_t*)&media_time)) {
9810a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        return ERROR_IO;
9820a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    }
9830a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                } else if (version == 0) {
9840a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    uint32_t sd;
9850a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int32_t mt;
9860a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    if (!mDataSource->getUInt32(entriesoffset, &sd) ||
9870a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                            !mDataSource->getUInt32(entriesoffset + 4, (uint32_t*)&mt)) {
9880a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        return ERROR_IO;
9890a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    }
9900a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    segment_duration = sd;
9910a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    media_time = mt;
9920a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                } else {
9930a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    return ERROR_IO;
9940a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                }
9950a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
996fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                uint64_t halfscale = mHeaderTimescale / 2;
997fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                segment_duration = (segment_duration * 1000000 + halfscale)/ mHeaderTimescale;
998fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                media_time = (media_time * 1000000 + halfscale) / mHeaderTimescale;
9990a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
10000a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int64_t duration;
10010a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int32_t samplerate;
10021391f933b49cfb56da9aa63f723de83b076cf888Robert Shih                if (!mLastTrack) {
10031391f933b49cfb56da9aa63f723de83b076cf888Robert Shih                    return ERROR_MALFORMED;
10041391f933b49cfb56da9aa63f723de83b076cf888Robert Shih                }
10050a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                if (mLastTrack->meta->findInt64(kKeyDuration, &duration) &&
10060a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        mLastTrack->meta->findInt32(kKeySampleRate, &samplerate)) {
10070a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
10080a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t delay = (media_time  * samplerate + 500000) / 1000000;
10090a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
10100a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
10110a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t paddingus = duration - (segment_duration + media_time);
1012465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                    if (paddingus < 0) {
1013465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        // track duration from media header (which is what kKeyDuration is) might
1014465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        // be slightly shorter than the segment duration, which would make the
1015465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        // padding negative. Clamp to zero.
1016465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        paddingus = 0;
1017465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                    }
10180a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t paddingsamples = (paddingus * samplerate + 500000) / 1000000;
10190a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    mLastTrack->meta->setInt32(kKeyEncoderPadding, paddingsamples);
10200a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                }
10210a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
10220a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            break;
10230a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        }
10240a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
1025ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('f', 'r', 'm', 'a'):
1026ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
10270517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
10280517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
102948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t original_fourcc;
1030ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset, &original_fourcc, 4) < 4) {
1031ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1032ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1033ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            original_fourcc = ntohl(original_fourcc);
1034ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("read original format: %d", original_fourcc);
1035ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc));
103648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t num_channels = 0;
103748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t sample_rate = 0;
103848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (AdjustChannelsAndRate(original_fourcc, &num_channels, &sample_rate)) {
103948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
104048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
104148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            }
1042ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1043ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1044ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1045ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('t', 'e', 'n', 'c'):
1046ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
10470517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
10480517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1049ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (chunk_size < 32) {
1050ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1051ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1052ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1053ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // tenc box contains 1 byte version, 3 byte flags, 3 byte default algorithm id, one byte
1054ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // default IV size, 16 bytes default KeyID
1055ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // (ISO 23001-7)
1056ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            char buf[4];
1057ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memset(buf, 0, 4);
1058ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 4, buf + 1, 3) < 3) {
1059ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1060ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1061ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t defaultAlgorithmId = ntohl(*((int32_t*)buf));
1062ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (defaultAlgorithmId > 1) {
1063ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only 0 (clear) and 1 (AES-128) are valid
1064ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1065ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1066ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1067ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memset(buf, 0, 4);
1068ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 7, buf + 3, 1) < 1) {
1069ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1070ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1071ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t defaultIVSize = ntohl(*((int32_t*)buf));
1072ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1073ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((defaultAlgorithmId == 0 && defaultIVSize != 0) ||
1074ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    (defaultAlgorithmId != 0 && defaultIVSize == 0)) {
1075ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only unencrypted data must have 0 IV size
1076ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1077ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            } else if (defaultIVSize != 0 &&
1078ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    defaultIVSize != 8 &&
1079ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    defaultIVSize != 16) {
1080ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only supported sizes are 0, 8 and 16
1081ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1082ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1083ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1084ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint8_t defaultKeyId[16];
1085ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1086ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 8, &defaultKeyId, 16) < 16) {
1087ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1088ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1089ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1090ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setInt32(kKeyCryptoMode, defaultAlgorithmId);
1091ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setInt32(kKeyCryptoDefaultIVSize, defaultIVSize);
1092ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setData(kKeyCryptoKey, 'tenc', defaultKeyId, 16);
1093ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1094ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1095ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
109620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'k', 'h', 'd'):
109720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
10980517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
10990517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1100ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            status_t err;
1101ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) {
1102ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber                return err;
110320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
110420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
110520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
110620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
110720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1108ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('p', 's', 's', 'h'):
1109ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
11100517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
11110517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1112ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            PsshInfo pssh;
1113ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1114ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 4, &pssh.uuid, 16) < 16) {
1115ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1116ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1117ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1118ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t psshdatalen = 0;
1119ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 20, &psshdatalen, 4) < 4) {
1120ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1121ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1122ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            pssh.datalen = ntohl(psshdatalen);
1123ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("pssh data size: %d", pssh.datalen);
1124ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (pssh.datalen + 20 > chunk_size) {
1125ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // pssh data length exceeds size of containing box
1126ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1127ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1128ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
11298da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            pssh.data = new (std::nothrow) uint8_t[pssh.datalen];
11308da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            if (pssh.data == NULL) {
11318da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen                return ERROR_MALFORMED;
11328da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            }
1133ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("allocated pssh @ %p", pssh.data);
1134ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ssize_t requested = (ssize_t) pssh.datalen;
1135ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 24, pssh.data, requested) < requested) {
1136ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1137ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1138ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mPssh.push_back(pssh);
1139ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1140ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1141ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1142ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
114320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'h', 'd'):
114420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
11450517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
11460517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1147202fbed96db40ec5fb43d633fc97601a15a6dd7aRobert Shih            if (chunk_data_size < 4 || mLastTrack == NULL) {
114820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
114920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
115020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
115120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t version;
115234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
115320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, &version, sizeof(version))
115420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(version)) {
115520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
115620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
115720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1158c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t timescale_offset;
115920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
116020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
116120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 16;
116220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else if (version == 0) {
116320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 8;
116420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
116520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
116620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
116720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
116820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t timescale;
116934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
117020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        timescale_offset, &timescale, sizeof(timescale))
117120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(timescale)) {
117220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
117320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
117420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
117520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->timescale = ntohl(timescale);
117620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1177c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            // 14496-12 says all ones means indeterminate, but some files seem to use
1178c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            // 0 instead. We treat both the same.
117905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            int64_t duration = 0;
118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
118134769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
118220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration, sizeof(duration))
118320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration)) {
118420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
118520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
1186c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (duration != -1) {
1187c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    duration = ntoh64(duration);
1188c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
118920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
119005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t duration32;
119134769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
119220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration32, sizeof(duration32))
119320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration32)) {
119420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
119520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
119605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (duration32 != 0xffffffff) {
119705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    duration = ntohl(duration32);
119805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
119920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1200c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (duration != 0) {
1201c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mLastTrack->meta->setInt64(
1202c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                        kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
1203c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
120420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12057a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            uint8_t lang[2];
12067a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            off64_t lang_offset;
12077a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            if (version == 1) {
12087a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                lang_offset = timescale_offset + 4 + 8;
12097a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            } else if (version == 0) {
12107a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                lang_offset = timescale_offset + 4 + 4;
12117a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            } else {
12127a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                return ERROR_IO;
12137a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            }
12147a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
12157a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            if (mDataSource->readAt(lang_offset, &lang, sizeof(lang))
12167a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                    < (ssize_t)sizeof(lang)) {
12177a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                return ERROR_IO;
12187a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            }
12197a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
12207a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // To get the ISO-639-2/T three character language code
12217a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // 1 bit pad followed by 3 5-bits characters. Each character
12227a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // is packed as the difference between its ASCII value and 0x60.
12237a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            char lang_code[4];
12247a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[0] = ((lang[0] >> 2) & 0x1f) + 0x60;
12257a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[1] = ((lang[0] & 0x3) << 3 | (lang[1] >> 5)) + 0x60;
12267a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[2] = (lang[1] & 0x1f) + 0x60;
12277a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[3] = '\0';
12287a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
12297a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            mLastTrack->meta->setCString(
12307a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                    kKeyMediaLanguage, lang_code);
12317a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
123220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
123320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
123420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
123520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'd'):
123620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
123720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 8) {
123820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
123920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
124020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
124120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8];
1242c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size < (off64_t)sizeof(buffer)) {
1243bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1244bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
1245bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
124634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
124720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, 8) < 8) {
124820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
124920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
125020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
125120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
125220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
125320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
125420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
125520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
125620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t entry_count = U32_AT(&buffer[4]);
125720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
125820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (entry_count > 1) {
12593b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // For 3GPP timed text, there could be multiple tx3g boxes contain
12603b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // multiple text display formats. These formats will be used to
12613b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // display the timed text.
1262ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // For encrypted files, there may also be more than one entry.
12633b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                const char *mime;
12643b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1265ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) &&
1266ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                        strcasecmp(mime, "application/octet-stream")) {
12673b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    // For now we only support a single type of media per track.
12683b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    mLastTrack->skipTrack = true;
12693b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    *offset += chunk_size;
12703b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    break;
12713b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                }
127220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1273c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
127420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + 8;
127520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            for (uint32_t i = 0; i < entry_count; ++i) {
127620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
127720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
127820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
127920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
128020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1281bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1282bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1283bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1284bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
128520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
128620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
128720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
128820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
128948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        case FOURCC('e', 'n', 'c', 'a'):
129020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
1291371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
129220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
129320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8 + 20];
129420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
129520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic AudioSampleEntry size.
129620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
129720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
129820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
129934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
130020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
130120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
130220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
130320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
130420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
130548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t num_channels = U16_AT(&buffer[16]);
130620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
130781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint16_t sample_size = U16_AT(&buffer[18]);
130881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
130981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
131048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (chunk_type != FOURCC('e', 'n', 'c', 'a')) {
131148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                // if the chunk type is enca, we'll get the type from the sinf/frma box later
131248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
131348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate);
131420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
131548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            ALOGV("*** coding='%s' %d channels, size %d, rate %d\n",
131681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                   chunk, num_channels, sample_size, sample_rate);
131720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
131820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
131920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1320c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
132120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
132220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
132320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
132420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
132520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
132620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
132720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1328bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1329bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1330bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1331bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
133220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
133320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
133420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
133520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
1336ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('e', 'n', 'c', 'v'):
133720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
1338e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('H', '2', '6', '3'):
1339e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('h', '2', '6', '3'):
134020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
13413b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'v', 'c', '1'):
13423b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'e', 'v', '1'):
134320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
13447be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber            mHasVideo = true;
13457be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
134620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[78];
134720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
134820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic VideoSampleEntry size.
134920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
135020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
135120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
135234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
135320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
135420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
135520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
135720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
135820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t width = U16_AT(&buffer[6 + 18]);
135920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t height = U16_AT(&buffer[6 + 20]);
136020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1361ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // The video sample is not standard-compliant if it has invalid dimension.
1362a6256238d9015c42129fe43791968768fe501efaJames Dong            // Use some default width and height value, and
1363a6256238d9015c42129fe43791968768fe501efaJames Dong            // let the decoder figure out the actual width and height (and thus
1364a6256238d9015c42129fe43791968768fe501efaJames Dong            // be prepared for INFO_FOMRAT_CHANGED event).
1365a6256238d9015c42129fe43791968768fe501efaJames Dong            if (width == 0)  width  = 352;
1366a6256238d9015c42129fe43791968768fe501efaJames Dong            if (height == 0) height = 288;
1367a6256238d9015c42129fe43791968768fe501efaJames Dong
1368134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            // printf("*** coding='%s' width=%d height=%d\n",
1369134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            //        chunk, width, height);
137020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1371ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (chunk_type != FOURCC('e', 'n', 'c', 'v')) {
1372ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // if the chunk type is encv, we'll get the type from the sinf/frma box later
1373ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
1374ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
137520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyWidth, width);
137620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyHeight, height);
137720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1378c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
137920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
138020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
138120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
138220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
138320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
138420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
138520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1386bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1387bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1388bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1389bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
139020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
139120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
139220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
139320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'c', 'o'):
139420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('c', 'o', '6', '4'):
139520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
139620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
139720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setChunkOffsetParams(
139820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
139920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14000517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
14010517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
140220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
140320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
140420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
140520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
140620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
140720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
140820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
140920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'c'):
141020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
141120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
141220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleToChunkParams(
141320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
141420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14150517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
14160517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
141720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
141820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
141920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
142020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
142120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
142220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
142320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
142420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'z'):
142520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'z', '2'):
142620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
142720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
142820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleSizeParams(
142920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
143020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14310517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
14320517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
143320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
143420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
143520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
143620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1437738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            size_t max_size;
143849110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            err = mLastTrack->sampleTable->getMaxSampleSize(&max_size);
143949110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber
144049110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            if (err != OK) {
144149110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber                return err;
144249110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            }
1443738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber
144405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (max_size != 0) {
144505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // Assume that a given buffer only contains at most 10 chunks,
144605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // each chunk originally prefixed with a 2 byte length will
144705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
144805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // and thus will grow by 2 bytes per chunk.
144905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
145005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            } else {
145105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // No size was specified. Pick a conservatively large size.
145205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                int32_t width, height;
1453f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                if (!mLastTrack->meta->findInt32(kKeyWidth, &width) ||
1454f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    !mLastTrack->meta->findInt32(kKeyHeight, &height)) {
145505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ALOGE("No width or height, assuming worst case 1080p");
1456f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    width = 1920;
1457f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    height = 1080;
145805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
1459f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar
14604256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen                const char *mime;
14614256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1462f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
1463f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // AVC requires compression ratio of at least 2, and uses
1464f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // macroblocks
1465f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    max_size = ((width + 15) / 16) * ((height + 15) / 16) * 192;
1466f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                } else {
1467f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // For all other formats there is no minimum compression
1468f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // ratio. Use compression ratio of 1.
1469f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    max_size = width * height * 3 / 2;
147005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
1471f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size);
147205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
1473113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong
14744256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            // NOTE: setting another piece of metadata invalidates any pointers (such as the
14754256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            // mimetype) previously obtained, so don't cache them.
1476113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            const char *mime;
1477113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1478113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            // Calculate average frame rate.
1479113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            if (!strncasecmp("video/", mime, 6)) {
1480113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                size_t nSamples = mLastTrack->sampleTable->countSamples();
1481113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                int64_t durationUs;
1482113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                if (mLastTrack->meta->findInt64(kKeyDuration, &durationUs)) {
1483113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                    if (durationUs > 0) {
1484113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                        int32_t frameRate = (nSamples * 1000000LL +
1485113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                                    (durationUs >> 1)) / durationUs;
1486113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                        mLastTrack->meta->setInt32(kKeyFrameRate, frameRate);
1487113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                    }
1488113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                }
1489113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            }
1490113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong
149120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
149220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
149320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
149420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 't', 's'):
149520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
14960517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
14970517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
149820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
149920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setTimeToSampleParams(
150020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
150120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
150220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
150320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
150420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
150520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
150620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
150720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
150820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15094931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        case FOURCC('c', 't', 't', 's'):
15104931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        {
15110517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
15120517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
15134931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            status_t err =
15144931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                mLastTrack->sampleTable->setCompositionTimeToSampleParams(
15154931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                        data_offset, chunk_data_size);
15164931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
15174931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            if (err != OK) {
15184931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                return err;
15194931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            }
15204931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
15214931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            break;
15224931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        }
15234931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
152420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 's'):
152520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
15260517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
15270517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
152820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
152920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSyncSampleParams(
153020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
153120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
153220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
153320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
153420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
153520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
153620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
153720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
153820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15394948818cb91176df74c972ac27b2f392b5d148bcJames Dong        // @xyz
15404948818cb91176df74c972ac27b2f392b5d148bcJames Dong        case FOURCC('\xA9', 'x', 'y', 'z'):
15414948818cb91176df74c972ac27b2f392b5d148bcJames Dong        {
15420517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
15430517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
15444948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Best case the total data length inside "@xyz" box
15454948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // would be 8, for instance "@xyz" + "\x00\x04\x15\xc7" + "0+0/",
15464948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // where "\x00\x04" is the text string length with value = 4,
15474948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // "\0x15\xc7" is the language code = en, and "0+0" is a
15484948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // location (string) value with longitude = 0 and latitude = 0.
15494948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (chunk_data_size < 8) {
15504948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_MALFORMED;
15514948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
15524948818cb91176df74c972ac27b2f392b5d148bcJames Dong
15534948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Worst case the location string length would be 18,
15544948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // for instance +90.0000-180.0000, without the trailing "/" and
15554948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // the string length + language code.
15564948818cb91176df74c972ac27b2f392b5d148bcJames Dong            char buffer[18];
15574948818cb91176df74c972ac27b2f392b5d148bcJames Dong
15584948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Substracting 5 from the data size is because the text string length +
15594948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // language code takes 4 bytes, and the trailing slash "/" takes 1 byte.
15604948818cb91176df74c972ac27b2f392b5d148bcJames Dong            off64_t location_length = chunk_data_size - 5;
15614948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (location_length >= (off64_t) sizeof(buffer)) {
15624948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_MALFORMED;
15634948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
15644948818cb91176df74c972ac27b2f392b5d148bcJames Dong
15654948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (mDataSource->readAt(
15664948818cb91176df74c972ac27b2f392b5d148bcJames Dong                        data_offset + 4, buffer, location_length) < location_length) {
15674948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_IO;
15684948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
15694948818cb91176df74c972ac27b2f392b5d148bcJames Dong
15704948818cb91176df74c972ac27b2f392b5d148bcJames Dong            buffer[location_length] = '\0';
15714948818cb91176df74c972ac27b2f392b5d148bcJames Dong            mFileMetaData->setCString(kKeyLocation, buffer);
15724948818cb91176df74c972ac27b2f392b5d148bcJames Dong            break;
15734948818cb91176df74c972ac27b2f392b5d148bcJames Dong        }
15744948818cb91176df74c972ac27b2f392b5d148bcJames Dong
157520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('e', 's', 'd', 's'):
157620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
15770517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
15780517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
157920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
158020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
158120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
158220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
158320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[256];
1584c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size > (off64_t)sizeof(buffer)) {
158520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
158620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
158720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
158834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
158920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
159020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
159120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
159220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
159320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
159420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
159520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
159620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
159720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
159820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
159920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
160020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1601ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            if (mPath.size() >= 2
1602ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
1603ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // Information from the ESDS must be relied on for proper
1604ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // setup of sample rate and channel count for MPEG4 Audio.
1605ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // The generic header appears to only contain generic
1606ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // information...
1607ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1608ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio(
1609ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                        &buffer[4], chunk_data_size - 4);
1610ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1611ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                if (err != OK) {
1612ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    return err;
1613ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                }
1614ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            }
1615ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
161620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
161720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
161820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
161920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', 'C'):
162020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
16210517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
16220517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1623d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson            sp<ABuffer> buffer = new ABuffer(chunk_data_size);
162420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
162534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
1626d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson                        data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
162720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
162820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
162920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
163020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
1631d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson                    kKeyAVCC, kTypeAVCC, buffer->data(), chunk_data_size);
163220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
163320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
163420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
16353b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'v', 'c', 'C'):
16363b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        {
16373b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            sp<ABuffer> buffer = new ABuffer(chunk_data_size);
16383b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
16393b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            if (mDataSource->readAt(
16403b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar                        data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
16413b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar                return ERROR_IO;
16423b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            }
16433b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
16443b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            mLastTrack->meta->setData(
16453b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar                    kKeyHVCC, kTypeHVCC, buffer->data(), chunk_data_size);
16463b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
16473b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            *offset += chunk_size;
16483b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            break;
16493b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        }
165020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1651244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        case FOURCC('d', '2', '6', '3'):
1652244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        {
16530517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
165417e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            /*
165517e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * d263 contains a fixed 7 bytes part:
165617e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   vendor - 4 bytes
165717e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   version - 1 byte
165817e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   level - 1 byte
165917e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   profile - 1 byte
166017e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * optionally, "d263" box itself may contain a 16-byte
166117e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * bit rate box (bitr)
166217e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   average bit rate - 4 bytes
166317e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   max bit rate - 4 bytes
166417e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             */
166517e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            char buffer[23];
166617e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            if (chunk_data_size != 7 &&
166717e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong                chunk_data_size != 23) {
166829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Incorrect D263 box size %lld", chunk_data_size);
1669244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                return ERROR_MALFORMED;
1670244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            }
1671244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1672244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            if (mDataSource->readAt(
1673244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                    data_offset, buffer, chunk_data_size) < chunk_data_size) {
1674244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                return ERROR_IO;
1675244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            }
1676244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1677244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size);
1678244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1679244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            break;
1680244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        }
1681244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
168272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'e', 't', 'a'):
168372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
168472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            uint8_t buffer[4];
1685c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size < (off64_t)sizeof(buffer)) {
16860517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen                *offset += chunk_size;
1687bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1688bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
1689bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
169072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
169172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, buffer, 4) < 4) {
16920517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen                *offset += chunk_size;
169372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
169472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
169572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
169672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (U32_AT(buffer) != 0) {
169772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                // Should be version 0, flags 0.
1698ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
1699ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // If it's not, let's assume this is one of those
1700ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // apparently malformed chunks that don't have flags
1701ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // and completely different semantics than what's
1702ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // in the MPEG4 specs and skip it.
1703ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                *offset += chunk_size;
1704ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                return OK;
170572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
170672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1707c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
170872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset = data_offset + sizeof(buffer);
170972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            while (*offset < stop_offset) {
171072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                status_t err = parseChunk(offset, depth + 1);
171172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
171272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
171372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
171472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
1715bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1716bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1717bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1718bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
171972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
172072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
172172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
17225d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('m', 'e', 'a', 'n'):
17235d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('n', 'a', 'm', 'e'):
172472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('d', 'a', 't', 'a'):
172572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
17260517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
17270517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
172872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mPath.size() == 6 && underMetaDataPath(mPath)) {
1729fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                status_t err = parseITunesMetaData(data_offset, chunk_data_size);
173072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
173172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
173272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
173372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
173472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
173572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
173672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
173772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
173872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
173972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'v', 'h', 'd'):
174072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
17410517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
17420517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1743c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (chunk_data_size < 32) {
174472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_MALFORMED;
174572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
174672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1747c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            uint8_t header[32];
174872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
174972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, header, sizeof(header))
175072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    < (ssize_t)sizeof(header)) {
175172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
175272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
175372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1754fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            uint64_t creationTime;
1755c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            uint64_t duration = 0;
175672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (header[0] == 1) {
175772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U64_AT(&header[4]);
1758fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                mHeaderTimescale = U32_AT(&header[20]);
1759c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                duration = U64_AT(&header[24]);
1760c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (duration == 0xffffffffffffffff) {
1761c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    duration = 0;
1762c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1763bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (header[0] != 0) {
1764bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
176572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            } else {
176672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U32_AT(&header[4]);
1767fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                mHeaderTimescale = U32_AT(&header[12]);
1768c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                uint32_t d32 = U32_AT(&header[16]);
1769c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (d32 == 0xffffffff) {
1770c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    d32 = 0;
1771c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1772c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                duration = d32;
1773c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1774c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (duration != 0) {
1775c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mFileMetaData->setInt64(kKeyDuration, duration * 1000000 / mHeaderTimescale);
177672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
177772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
177872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            String8 s;
177972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            convertTimeToDate(creationTime, &s);
178072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
178172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(kKeyDate, s.string());
178272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
178372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
178472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
178572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1786c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        case FOURCC('m', 'e', 'h', 'd'):
1787c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        {
1788c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            *offset += chunk_size;
1789c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1790c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (chunk_data_size < 8) {
1791c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_MALFORMED;
1792c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1793c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1794c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            uint8_t flags[4];
1795c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (mDataSource->readAt(
1796c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                        data_offset, flags, sizeof(flags))
1797c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    < (ssize_t)sizeof(flags)) {
1798c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_IO;
1799c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1800c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1801c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            uint64_t duration = 0;
1802c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (flags[0] == 1) {
1803c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                // 64 bit
1804c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (chunk_data_size < 12) {
1805c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    return ERROR_MALFORMED;
1806c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1807c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mDataSource->getUInt64(data_offset + 4, &duration);
1808c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (duration == 0xffffffffffffffff) {
1809c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    duration = 0;
1810c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1811c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            } else if (flags[0] == 0) {
1812c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                // 32 bit
1813c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                uint32_t d32;
1814c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mDataSource->getUInt32(data_offset + 4, &d32);
1815c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (d32 == 0xffffffff) {
1816c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    d32 = 0;
1817c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1818c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                duration = d32;
1819c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            } else {
1820c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_MALFORMED;
1821c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1822c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1823c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (duration != 0) {
1824c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mFileMetaData->setInt64(kKeyDuration, duration * 1000000 / mHeaderTimescale);
1825c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1826c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1827c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            break;
1828c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        }
1829c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1830dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        case FOURCC('m', 'd', 'a', 't'):
1831dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        {
1832ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("mdat chunk, drm: %d", mIsDrm);
1833dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (!mIsDrm) {
1834dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                *offset += chunk_size;
1835dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                break;
1836dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
1837dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
1838dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (chunk_size < 8) {
1839dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
1840dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
1841dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
1842dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return parseDrmSINF(offset, data_offset);
1843dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
1844dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
18453b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        case FOURCC('h', 'd', 'l', 'r'):
18463b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        {
18470517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
18480517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
18493b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t buffer;
18503b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (mDataSource->readAt(
18513b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                        data_offset + 8, &buffer, 4) < 4) {
18523b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_IO;
18533b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
18543b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
18553b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type = ntohl(buffer);
18563b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            // For the 3GPP file format, the handler-type within the 'hdlr' box
1857e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            // shall be 'text'. We also want to support 'sbtl' handler type
1858e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            // for a practical reason as various MPEG4 containers use it.
1859e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            if (type == FOURCC('t', 'e', 'x', 't') || type == FOURCC('s', 'b', 't', 'l')) {
18603b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
18613b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
18623b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
18633b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            break;
18643b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        }
18653b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
1866c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        case FOURCC('t', 'r', 'e', 'x'):
1867c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        {
1868c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            *offset += chunk_size;
1869c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1870c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (chunk_data_size < 24) {
1871c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_IO;
1872c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1873c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            uint32_t duration;
1874c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            Trex trex;
1875c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (!mDataSource->getUInt32(data_offset + 4, &trex.track_ID) ||
1876c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                !mDataSource->getUInt32(data_offset + 8, &trex.default_sample_description_index) ||
1877c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                !mDataSource->getUInt32(data_offset + 12, &trex.default_sample_duration) ||
1878c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                !mDataSource->getUInt32(data_offset + 16, &trex.default_sample_size) ||
1879c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                !mDataSource->getUInt32(data_offset + 20, &trex.default_sample_flags)) {
1880c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_IO;
1881c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1882c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            mTrex.add(trex);
1883c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            break;
1884c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        }
1885c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
18867a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        case FOURCC('t', 'x', '3', 'g'):
18877a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        {
18883b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type;
18893b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            const void *data;
18903b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            size_t size = 0;
18913b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (!mLastTrack->meta->findData(
18923b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    kKeyTextFormatData, &type, &data, &size)) {
18933b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                size = 0;
18943b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
18953b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
18968da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            uint8_t *buffer = new (std::nothrow) uint8_t[size + chunk_size];
18978da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            if (buffer == NULL) {
18988da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen                return ERROR_MALFORMED;
18998da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            }
19003b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
19013b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (size > 0) {
19023b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                memcpy(buffer, data, size);
19033b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
19043b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
19053b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size))
19063b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    < chunk_size) {
19073b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                delete[] buffer;
19083b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                buffer = NULL;
19093b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
19100517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen                // advance read pointer so we don't end up reading this again
19110517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen                *offset += chunk_size;
19123b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_IO;
19133b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
19143b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
19153b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            mLastTrack->meta->setData(
19163b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    kKeyTextFormatData, 0, buffer, size + chunk_size);
19173b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
19183b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            delete[] buffer;
19197a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
19207a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            *offset += chunk_size;
19217a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            break;
19227a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        }
19237a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
1924515e855eae78aa495da58356486aaa666cb57fd1James Dong        case FOURCC('c', 'o', 'v', 'r'):
1925515e855eae78aa495da58356486aaa666cb57fd1James Dong        {
19260517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
19270517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1928515e855eae78aa495da58356486aaa666cb57fd1James Dong            if (mFileMetaData != NULL) {
19293856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("chunk_data_size = %lld and data_offset = %lld",
1930515e855eae78aa495da58356486aaa666cb57fd1James Dong                        chunk_data_size, data_offset);
19311552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1);
1932515e855eae78aa495da58356486aaa666cb57fd1James Dong                if (mDataSource->readAt(
19331552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                    data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) {
1934515e855eae78aa495da58356486aaa666cb57fd1James Dong                    return ERROR_IO;
1935515e855eae78aa495da58356486aaa666cb57fd1James Dong                }
1936515e855eae78aa495da58356486aaa666cb57fd1James Dong                const int kSkipBytesOfDataBox = 16;
1937515e855eae78aa495da58356486aaa666cb57fd1James Dong                mFileMetaData->setData(
1938515e855eae78aa495da58356486aaa666cb57fd1James Dong                    kKeyAlbumArt, MetaData::TYPE_NONE,
19391552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                    buffer->data() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox);
1940515e855eae78aa495da58356486aaa666cb57fd1James Dong            }
1941515e855eae78aa495da58356486aaa666cb57fd1James Dong
1942515e855eae78aa495da58356486aaa666cb57fd1James Dong            break;
1943515e855eae78aa495da58356486aaa666cb57fd1James Dong        }
1944515e855eae78aa495da58356486aaa666cb57fd1James Dong
1945fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('t', 'i', 't', 'l'):
1946fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('p', 'e', 'r', 'f'):
1947fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'u', 't', 'h'):
1948fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('g', 'n', 'r', 'e'):
1949fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'l', 'b', 'm'):
1950fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('y', 'r', 'r', 'c'):
1951fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
19520517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
19530517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1954fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            status_t err = parse3GPPMetaData(data_offset, chunk_data_size, depth);
1955fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
1956fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (err != OK) {
1957fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                return err;
1958fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
1959fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
1960fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
1961fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
1962fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
1963328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        case FOURCC('I', 'D', '3', '2'):
1964328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        {
19650517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
19660517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1967328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            if (chunk_data_size < 6) {
1968328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                return ERROR_MALFORMED;
1969328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            }
1970328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
1971328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            parseID3v2MetaData(data_offset + 6);
1972328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
1973328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            break;
1974328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        }
1975328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
19765d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('-', '-', '-', '-'):
19775d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        {
19785d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentMean.clear();
19795d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentName.clear();
19805d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentData.clear();
19815d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            *offset += chunk_size;
19825d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            break;
19835d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        }
19845d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen
198505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('s', 'i', 'd', 'x'):
198605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        {
198705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            parseSegmentIndex(data_offset, chunk_data_size);
198805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset += chunk_size;
198905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return UNKNOWN_ERROR; // stop parsing after sidx
199005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
199105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
199220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
199320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
199420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
199520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
199620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
199720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
199820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
199920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
200020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
200120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
200205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) {
200305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen  ALOGV("MPEG4Extractor::parseSegmentIndex");
200405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
200505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 12) {
200605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      return -EINVAL;
200705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
200805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
200905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
201005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) {
201105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
201205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
201305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
201405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t version = flags >> 24;
201505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    flags &= 0xffffff;
201605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
201705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx version %d", version);
201805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
201905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t referenceId;
202005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, &referenceId)) {
202105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
202205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
202305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
202405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t timeScale;
202505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 8, &timeScale)) {
202605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
202705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
202805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx refid/timescale: %d/%d", referenceId, timeScale);
202905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
203005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t earliestPresentationTime;
203105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t firstOffset;
203205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
203305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 12;
203405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 12;
203505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
203605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (version == 0) {
203705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 8) {
203805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
203905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
204005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t tmp;
204105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
204205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
204305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
204405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        earliestPresentationTime = tmp;
204505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset + 4, &tmp)) {
204605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
204705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
204805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        firstOffset = tmp;
204905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 8;
205005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 8;
205105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
205205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 16) {
205305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
205405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
205505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset, &earliestPresentationTime)) {
205605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
205705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
205805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset + 8, &firstOffset)) {
205905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
206005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
206105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 16;
206205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 16;
206305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
2064a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("sidx pres/off: %" PRIu64 "/%" PRIu64, earliestPresentationTime, firstOffset);
206505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
206605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 4) {
206705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
206805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
206905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
207005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint16_t referenceCount;
207105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt16(offset + 2, &referenceCount)) {
207205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
207305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
207405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 4;
207505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 4;
207605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("refcount: %d", referenceCount);
207705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
207805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < referenceCount * 12) {
207905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
208005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
208105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
208205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t total_duration = 0;
208305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    for (unsigned int i = 0; i < referenceCount; i++) {
208405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t d1, d2, d3;
208505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
208605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &d1) ||     // size
208705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            !mDataSource->getUInt32(offset + 4, &d2) || // duration
208805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            !mDataSource->getUInt32(offset + 8, &d3)) { // flags
208905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
209005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
209105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
209205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (d1 & 0x80000000) {
209305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGW("sub-sidx boxes not supported yet");
209405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
209505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool sap = d3 & 0x80000000;
20963f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen        uint32_t saptype = (d3 >> 28) & 7;
20973f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen        if (!sap || (saptype != 1 && saptype != 2)) {
20983f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            // type 1 and 2 are sync samples
20993f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            ALOGW("not a stream access point, or unsupported type: %08x", d3);
210005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
210105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        total_duration += d2;
210205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 12;
210305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV(" item %d, %08x %08x %08x", i, d1, d2, d3);
210405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        SidxEntry se;
210505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        se.mSize = d1 & 0x7fffffff;
210605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        se.mDurationUs = 1000000LL * d2 / timeScale;
210705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mSidxEntries.add(se);
210805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
210905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2110c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    uint64_t sidxDuration = total_duration * 1000000 / timeScale;
211105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
211205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t metaDuration;
211305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mLastTrack->meta->findInt64(kKeyDuration, &metaDuration) || metaDuration == 0) {
2114c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        mLastTrack->meta->setInt64(kKeyDuration, sidxDuration);
211505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
211605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
211705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
211805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
211905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
212005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2121ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huberstatus_t MPEG4Extractor::parseTrackHeader(
2122c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t data_offset, off64_t data_size) {
2123ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (data_size < 4) {
2124ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_MALFORMED;
2125ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2126ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2127ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint8_t version;
2128ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (mDataSource->readAt(data_offset, &version, 1) < 1) {
2129ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_IO;
2130ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2131ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2132ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    size_t dynSize = (version == 1) ? 36 : 24;
2133ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2134ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint8_t buffer[36 + 60];
2135ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2136c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    if (data_size != (off64_t)dynSize + 60) {
2137ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_MALFORMED;
2138ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2139ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2140ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (mDataSource->readAt(
2141ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber                data_offset, buffer, data_size) < (ssize_t)data_size) {
2142ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_IO;
2143ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2144ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2145ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint64_t ctime, mtime, duration;
2146ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t id;
2147ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2148ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (version == 1) {
2149ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        ctime = U64_AT(&buffer[4]);
2150ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mtime = U64_AT(&buffer[12]);
2151ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        id = U32_AT(&buffer[20]);
2152ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        duration = U64_AT(&buffer[28]);
215304022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen    } else if (version == 0) {
2154ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        ctime = U32_AT(&buffer[4]);
2155ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mtime = U32_AT(&buffer[8]);
2156ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        id = U32_AT(&buffer[12]);
2157ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        duration = U32_AT(&buffer[20]);
215804022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen    } else {
215904022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen        return ERROR_UNSUPPORTED;
2160ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2161ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2162ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    mLastTrack->meta->setInt32(kKeyTrackID, id);
2163ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2164ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    size_t matrixOffset = dynSize + 16;
2165ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a00 = U32_AT(&buffer[matrixOffset]);
2166ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a01 = U32_AT(&buffer[matrixOffset + 4]);
2167ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t dx = U32_AT(&buffer[matrixOffset + 8]);
2168ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a10 = U32_AT(&buffer[matrixOffset + 12]);
2169ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a11 = U32_AT(&buffer[matrixOffset + 16]);
2170ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t dy = U32_AT(&buffer[matrixOffset + 20]);
2171ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2172ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#if 0
2173df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("x' = %.2f * x + %.2f * y + %.2f",
2174ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber         a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f);
2175df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("y' = %.2f * x + %.2f * y + %.2f",
2176ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber         a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f);
2177ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#endif
2178ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2179ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t rotationDegrees;
2180ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2181ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    static const int32_t kFixedOne = 0x10000;
2182ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) {
2183ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        // Identity, no rotation
2184ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 0;
2185ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) {
2186ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 90;
2187ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) {
2188ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 270;
2189ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) {
2190ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 180;
2191ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else {
21925ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("We only support 0,90,180,270 degree rotation matrices");
2193ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 0;
2194ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2195ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2196ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (rotationDegrees != 0) {
2197ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees);
2198ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2199ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2200b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    // Handle presentation display size, which could be different
2201b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    // from the image size indicated by kKeyWidth and kKeyHeight.
2202ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t width = U32_AT(&buffer[dynSize + 52]);
2203ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t height = U32_AT(&buffer[dynSize + 56]);
2204b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    mLastTrack->meta->setInt32(kKeyDisplayWidth, width >> 16);
2205b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    mLastTrack->meta->setInt32(kKeyDisplayHeight, height >> 16);
2206ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2207ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    return OK;
2208ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber}
2209ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2210fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhéstatus_t MPEG4Extractor::parseITunesMetaData(off64_t offset, size_t size) {
221172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (size < 4) {
221272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_MALFORMED;
221372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
221472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
22158da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    uint8_t *buffer = new (std::nothrow) uint8_t[size + 1];
22168da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    if (buffer == NULL) {
22178da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        return ERROR_MALFORMED;
22188da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    }
221972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (mDataSource->readAt(
222072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                offset, buffer, size) != (ssize_t)size) {
222172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        delete[] buffer;
222272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        buffer = NULL;
222372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
222472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_IO;
222572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
222672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
222772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t flags = U32_AT(buffer);
222872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
222972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t metadataKey = 0;
22305d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    char chunk[5];
22315d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    MakeFourCCString(mPath[4], chunk);
22325d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    ALOGV("meta: %s @ %lld", chunk, offset);
223372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    switch (mPath[4]) {
223472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'a', 'l', 'b'):
223572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
223672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbum;
223772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
223872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
223972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'A', 'R', 'T'):
224072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
224172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyArtist;
224272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
224372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
224466ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        case FOURCC('a', 'A', 'R', 'T'):
224566ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        {
224666ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            metadataKey = kKeyAlbumArtist;
224766ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            break;
224866ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        }
224972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'd', 'a', 'y'):
225072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
225172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyYear;
225272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
225372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
225472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'n', 'a', 'm'):
225572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
225672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyTitle;
225772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
225872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
225972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'w', 'r', 't'):
226072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
226172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyWriter;
226272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
226372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
226472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('c', 'o', 'v', 'r'):
226572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
226672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbumArt;
226772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
226872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
226972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('g', 'n', 'r', 'e'):
227072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
227172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyGenre;
227272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
227372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
227426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC(0xa9, 'g', 'e', 'n'):
227526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
227626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            metadataKey = kKeyGenre;
227726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
227826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
227911f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        case FOURCC('c', 'p', 'i', 'l'):
228011f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        {
228111f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            if (size == 9 && flags == 21) {
228211f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                char tmp[16];
228311f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                sprintf(tmp, "%d",
228411f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                        (int)buffer[size - 1]);
228511f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen
228611f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                mFileMetaData->setCString(kKeyCompilation, tmp);
228711f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            }
228811f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            break;
228911f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        }
229072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('t', 'r', 'k', 'n'):
229172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
229272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (size == 16 && flags == 0) {
229372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char tmp[16];
2294afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTrack = (uint16_t*)&buffer[10];
2295afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTotalTracks = (uint16_t*)&buffer[12];
2296afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                sprintf(tmp, "%d/%d", ntohs(*pTrack), ntohs(*pTotalTracks));
229772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
229872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
229972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
230072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
230172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
230226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC('d', 'i', 's', 'k'):
230326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
2304afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik            if ((size == 14 || size == 16) && flags == 0) {
230526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                char tmp[16];
2306afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pDisc = (uint16_t*)&buffer[10];
2307afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTotalDiscs = (uint16_t*)&buffer[12];
2308afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                sprintf(tmp, "%d/%d", ntohs(*pDisc), ntohs(*pTotalDiscs));
230926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
231026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(kKeyDiscNumber, tmp);
231126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            }
231226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
231326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
23145d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('-', '-', '-', '-'):
23155d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        {
23165d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            buffer[size] = '\0';
23175d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            switch (mPath[5]) {
23185d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('m', 'e', 'a', 'n'):
23195d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentMean.setTo((const char *)buffer + 4);
23205d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
23215d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('n', 'a', 'm', 'e'):
23225d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentName.setTo((const char *)buffer + 4);
23235d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
23245d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('d', 'a', 't', 'a'):
23255d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentData.setTo((const char *)buffer + 8);
23265d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
23275d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            }
23288c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
23298c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // Once we have a set of mean/name/data info, go ahead and process
23308c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // it to see if its something we are interested in.  Whether or not
23318c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // were are interested in the specific tag, make sure to clear out
23328c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // the set so we can be ready to process another tuple should one
23338c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // show up later in the file.
23348c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            if ((mLastCommentMean.length() != 0) &&
23358c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                (mLastCommentName.length() != 0) &&
23368c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                (mLastCommentData.length() != 0)) {
23378c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
23388c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                if (mLastCommentMean == "com.apple.iTunes"
23398c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        && mLastCommentName == "iTunSMPB") {
23408c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    int32_t delay, padding;
23418c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    if (sscanf(mLastCommentData,
23428c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                               " %*x %x %x %*x", &delay, &padding) == 2) {
23438c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
23448c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        mLastTrack->meta->setInt32(kKeyEncoderPadding, padding);
23458c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    }
23465d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                }
23478c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
23485d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentMean.clear();
23495d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentName.clear();
23505d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentData.clear();
23515d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            }
23525d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            break;
23535d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        }
235426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
235572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        default:
235672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
235772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
235872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
2359328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    if (size >= 8 && metadataKey && !mFileMetaData->hasData(metadataKey)) {
236072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        if (metadataKey == kKeyAlbumArt) {
236172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setData(
236272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    kKeyAlbumArt, MetaData::TYPE_NONE,
236372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    buffer + 8, size - 8);
236472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else if (metadataKey == kKeyGenre) {
236572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (flags == 0) {
236626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // uint8_t genre code, iTunes genre codes are
236726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // the standard id3 codes, except they start
236826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // at 1 instead of 0 (e.g. Pop is 14, not 13)
236926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // We use standard id3 numbering, so subtract 1.
237026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                int genrecode = (int)buffer[size - 1];
237126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                genrecode--;
237226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                if (genrecode < 0) {
237326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                    genrecode = 255; // reserved for 'unknown genre'
237426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                }
237572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char genre[10];
237626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                sprintf(genre, "%d", genrecode);
237772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
237872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(metadataKey, genre);
237926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            } else if (flags == 1) {
238026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // custom genre string
238126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                buffer[size] = '\0';
238226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
238326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(
238426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                        metadataKey, (const char *)buffer + 8);
238572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
238672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else {
238772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            buffer[size] = '\0';
238872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
238972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(
239072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    metadataKey, (const char *)buffer + 8);
239172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
239272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
239372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
239472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    delete[] buffer;
239572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    buffer = NULL;
239672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
239772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return OK;
239872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
239972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
2400fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhéstatus_t MPEG4Extractor::parse3GPPMetaData(off64_t offset, size_t size, int depth) {
2401fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    if (size < 4) {
2402fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        return ERROR_MALFORMED;
2403fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2404fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
24058da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    uint8_t *buffer = new (std::nothrow) uint8_t[size];
24068da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    if (buffer == NULL) {
24078da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        return ERROR_MALFORMED;
24088da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    }
2409fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    if (mDataSource->readAt(
2410fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                offset, buffer, size) != (ssize_t)size) {
2411fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        delete[] buffer;
2412fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        buffer = NULL;
2413fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2414fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        return ERROR_IO;
2415fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2416fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2417fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    uint32_t metadataKey = 0;
2418fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    switch (mPath[depth]) {
2419fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('t', 'i', 't', 'l'):
2420fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2421fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyTitle;
2422fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2423fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2424fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('p', 'e', 'r', 'f'):
2425fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2426fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyArtist;
2427fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2428fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2429fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'u', 't', 'h'):
2430fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2431fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyWriter;
2432fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2433fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2434fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('g', 'n', 'r', 'e'):
2435fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2436fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyGenre;
2437fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2438fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2439fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'l', 'b', 'm'):
2440fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2441fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (buffer[size - 1] != '\0') {
2442fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé              char tmp[4];
2443fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé              sprintf(tmp, "%u", buffer[size - 1]);
2444fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2445fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé              mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
2446fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2447fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2448fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyAlbum;
2449fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2450fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2451fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('y', 'r', 'r', 'c'):
2452fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2453fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            char tmp[5];
2454fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            uint16_t year = U16_AT(&buffer[4]);
2455fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2456fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (year < 10000) {
2457fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                sprintf(tmp, "%u", year);
2458fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2459fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                mFileMetaData->setCString(kKeyYear, tmp);
2460fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2461fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2462fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2463fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2464fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        default:
2465fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2466fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2467fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2468fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    if (metadataKey > 0) {
2469fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        bool isUTF8 = true; // Common case
2470fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        char16_t *framedata = NULL;
2471fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        int len16 = 0; // Number of UTF-16 characters
2472fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2473fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        // smallest possible valid UTF-16 string w BOM: 0xfe 0xff 0x00 0x00
2474fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        if (size - 6 >= 4) {
2475fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            len16 = ((size - 6) / 2) - 1; // don't include 0x0000 terminator
2476fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            framedata = (char16_t *)(buffer + 6);
2477fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (0xfffe == *framedata) {
2478fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                // endianness marker (BOM) doesn't match host endianness
2479fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                for (int i = 0; i < len16; i++) {
2480fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                    framedata[i] = bswap_16(framedata[i]);
2481fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                }
2482fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                // BOM is now swapped to 0xfeff, we will execute next block too
2483fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2484fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2485fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (0xfeff == *framedata) {
2486fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                // Remove the BOM
2487fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                framedata++;
2488fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                len16--;
2489fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                isUTF8 = false;
2490fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2491fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // else normal non-zero-length UTF-8 string
2492fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // we can't handle UTF-16 without BOM as there is no other
2493fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // indication of encoding.
2494fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2495fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2496fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        if (isUTF8) {
2497fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            mFileMetaData->setCString(metadataKey, (const char *)buffer + 6);
2498fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        } else {
2499fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // Convert from UTF-16 string to UTF-8 string.
2500fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            String8 tmpUTF8str(framedata, len16);
2501fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            mFileMetaData->setCString(metadataKey, tmpUTF8str.string());
2502fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2503fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2504fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2505fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    delete[] buffer;
2506fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    buffer = NULL;
2507fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2508fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    return OK;
2509fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé}
2510fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2511328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhévoid MPEG4Extractor::parseID3v2MetaData(off64_t offset) {
2512328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    ID3 id3(mDataSource, true /* ignorev1 */, offset);
2513328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2514328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    if (id3.isValid()) {
2515328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        struct Map {
2516328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            int key;
2517328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            const char *tag1;
2518328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            const char *tag2;
2519328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        };
2520328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        static const Map kMap[] = {
2521328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyAlbum, "TALB", "TAL" },
2522328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyArtist, "TPE1", "TP1" },
2523328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyAlbumArtist, "TPE2", "TP2" },
2524328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyComposer, "TCOM", "TCM" },
2525328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyGenre, "TCON", "TCO" },
2526328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyTitle, "TIT2", "TT2" },
2527328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyYear, "TYE", "TYER" },
2528328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyAuthor, "TXT", "TEXT" },
2529328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyCDTrackNumber, "TRK", "TRCK" },
2530328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyDiscNumber, "TPA", "TPOS" },
2531328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyCompilation, "TCP", "TCMP" },
2532328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        };
2533328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
2534328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2535328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        for (size_t i = 0; i < kNumMapEntries; ++i) {
2536328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            if (!mFileMetaData->hasData(kMap[i].key)) {
2537328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                ID3::Iterator *it = new ID3::Iterator(id3, kMap[i].tag1);
2538328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                if (it->done()) {
2539328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    delete it;
2540328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    it = new ID3::Iterator(id3, kMap[i].tag2);
2541328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                }
2542328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2543328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                if (it->done()) {
2544328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    delete it;
2545328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    continue;
2546328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                }
2547328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2548328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                String8 s;
2549328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                it->getString(&s);
2550328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                delete it;
2551328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2552328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                mFileMetaData->setCString(kMap[i].key, s);
2553328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            }
2554328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        }
2555328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2556328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        size_t dataSize;
2557328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        String8 mime;
2558328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        const void *data = id3.getAlbumArt(&dataSize, &mime);
2559328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2560328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        if (data) {
2561328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            mFileMetaData->setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize);
2562328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            mFileMetaData->setCString(kKeyAlbumArtMIME, mime.string());
2563328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        }
2564328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    }
2565328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé}
2566328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2567693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
256820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
256920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
2570693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return NULL;
257120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
257220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
257320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
257420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
257520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
2576693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber            return NULL;
257720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
257820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
257920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
258020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
258120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
258220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2583371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
2584371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
2585371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
2586371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
2587c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
2588c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    Trex *trex = NULL;
2589c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    int32_t trackId;
2590c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    if (track->meta->findInt32(kKeyTrackID, &trackId)) {
2591c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        for (size_t i = 0; i < mTrex.size(); i++) {
2592c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            Trex *t = &mTrex.editItemAt(index);
2593c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (t->track_ID == (uint32_t) trackId) {
2594c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                trex = t;
2595c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                break;
2596c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
2597c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        }
2598c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    }
2599c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
2600a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("getTrack called, pssh: %zu", mPssh.size());
2601ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2602942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    return new MPEG4Source(this,
260305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            track->meta, mDataSource, track->timescale, track->sampleTable,
2604c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            mSidxEntries, trex, mMoofOffset);
260520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
260620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2607bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber// static
2608bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) {
2609bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const char *mime;
2610bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    CHECK(track->meta->findCString(kKeyMIMEType, &mime));
2611bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2612bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    uint32_t type;
2613bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const void *data;
2614bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    size_t size;
2615bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
2616bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyAVCC, &type, &data, &size)
2617bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeAVCC) {
2618bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
2619bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
26203b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
26213b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        if (!track->meta->findData(kKeyHVCC, &type, &data, &size)
26223b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar                    || type != kTypeHVCC) {
26233b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            return ERROR_MALFORMED;
26243b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        }
2625bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
2626bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
2627bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyESDS, &type, &data, &size)
2628bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeESDS) {
2629bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
2630bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
2631bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    }
2632bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2633ce171998009e1abcb0c718c0aee495fcd33645e2Robert Shih    if (track->sampleTable == NULL || !track->sampleTable->isValid()) {
2634169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        // Make sure we have all the metadata we need.
2635ce171998009e1abcb0c718c0aee495fcd33645e2Robert Shih        ALOGE("stbl atom missing/invalid.");
2636169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        return ERROR_MALFORMED;
2637169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber    }
2638169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber
2639bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    return OK;
2640bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber}
2641bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2642f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivitypedef enum {
2643f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_NONE             = -1,
2644f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_NULL_OBJECT      = 0,
2645f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_MAIN         = 1, /**< Main profile                              */
2646f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_AAC_LC           = 2,   /**< Low Complexity object                     */
2647f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_SSR          = 3,
2648f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_LTP          = 4,
2649f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_SBR              = 5,
2650f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_SCAL         = 6,
2651f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_TWIN_VQ          = 7,
2652f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_CELP             = 8,
2653f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_HVXC             = 9,
2654f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_10          = 10, /**< (reserved)                                */
2655f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_11          = 11, /**< (reserved)                                */
2656f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_TTSI             = 12, /**< TTSI Object                               */
2657f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MAIN_SYNTH       = 13, /**< Main Synthetic object                     */
2658f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_WAV_TAB_SYNTH    = 14, /**< Wavetable Synthesis object                */
2659f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_GEN_MIDI         = 15, /**< General MIDI object                       */
2660f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ALG_SYNTH_AUD_FX = 16, /**< Algorithmic Synthesis and Audio FX object */
2661f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_AAC_LC        = 17,   /**< Error Resilient(ER) AAC Low Complexity    */
2662f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_18          = 18, /**< (reserved)                                */
2663f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_AAC_LTP       = 19, /**< Error Resilient(ER) AAC LTP object        */
2664f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_AAC_SCAL      = 20,   /**< Error Resilient(ER) AAC Scalable object   */
2665f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_TWIN_VQ       = 21, /**< Error Resilient(ER) TwinVQ object         */
2666f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_BSAC          = 22,   /**< Error Resilient(ER) BSAC object           */
2667f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_AAC_LD        = 23,   /**< Error Resilient(ER) AAC LowDelay object   */
2668f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_CELP          = 24, /**< Error Resilient(ER) CELP object           */
2669f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_HVXC          = 25, /**< Error Resilient(ER) HVXC object           */
2670f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_HILN          = 26, /**< Error Resilient(ER) HILN object           */
2671f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_PARA          = 27, /**< Error Resilient(ER) Parametric object     */
2672f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_28          = 28, /**< might become SSC                          */
2673f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_PS               = 29,   /**< PS, Parametric Stereo (includes SBR)      */
2674f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MPEGS            = 30, /**< MPEG Surround                             */
2675f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2676f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ESCAPE           = 31,   /**< Signal AOT uses more than 5 bits          */
2677f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2678f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MP3ONMP4_L1      = 32, /**< MPEG-Layer1 in mp4                        */
2679f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MP3ONMP4_L2      = 33, /**< MPEG-Layer2 in mp4                        */
2680f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MP3ONMP4_L3      = 34, /**< MPEG-Layer3 in mp4                        */
2681f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_35          = 35, /**< might become DST                          */
2682f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_36          = 36, /**< might become ALS                          */
2683f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_SLS          = 37, /**< AAC + SLS                                 */
2684f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_SLS              = 38, /**< SLS                                       */
2685f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_AAC_ELD       = 39, /**< AAC Enhanced Low Delay                    */
2686f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2687f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_USAC             = 42, /**< USAC                                      */
2688f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_SAOC             = 43, /**< SAOC                                      */
2689f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_LD_MPEGS         = 44, /**< Low Delay MPEG Surround                   */
2690f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2691f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD50           = 50,  /**< Interim AOT for Rsvd50                   */
2692f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi} AUDIO_OBJECT_TYPE;
2693f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2694ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
2695ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        const void *esds_data, size_t esds_size) {
2696ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    ESDS esds(esds_data, esds_size);
269781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
269881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    uint8_t objectTypeIndication;
269981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
270081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return ERROR_MALFORMED;
270181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
270281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
270381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (objectTypeIndication == 0xe1) {
270481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        // This isn't MPEG4 audio at all, it's QCELP 14k...
270581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
270681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return OK;
270781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
270881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
2709633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong    if (objectTypeIndication  == 0x6b) {
2710633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // The media subtype is MP3 audio
2711633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // Our software MP3 audio decoder may not be able to handle
2712633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // packetized MP3 audio; for now, lets just return ERROR_UNSUPPORTED
271329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("MP3 track in MP4/3GPP file is not supported");
2714633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        return ERROR_UNSUPPORTED;
2715633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong    }
2716633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong
2717ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    const uint8_t *csd;
2718ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    size_t csd_size;
2719ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (esds.getCodecSpecificInfo(
2720ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                (const void **)&csd, &csd_size) != OK) {
2721ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
2722ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2723ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2724ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#if 0
2725ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    printf("ESD of size %d\n", csd_size);
2726ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    hexdump(csd, csd_size);
2727ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#endif
2728ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2729a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    if (csd_size == 0) {
2730a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // There's no further information, i.e. no codec specific data
2731a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // Let's assume that the information provided in the mpeg4 headers
2732a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // is accurate and hope for the best.
2733a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
2734a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        return OK;
2735a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    }
2736a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
2737ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (csd_size < 2) {
2738ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
2739ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2740ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
274100307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent    static uint32_t kSamplingRate[] = {
274200307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
274300307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        16000, 12000, 11025, 8000, 7350
274400307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent    };
274500307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent
2746aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    ABitReader br(csd, csd_size);
2747aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    uint32_t objectType = br.getBits(5);
2748ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2749aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    if (objectType == 31) {  // AAC-ELD => additional 6 bits
2750aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        objectType = 32 + br.getBits(6);
2751ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2752ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2753db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent    //keep AOT type
2754db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent    mLastTrack->meta->setInt32(kKeyAACAOT, objectType);
2755db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent
2756aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    uint32_t freqIndex = br.getBits(4);
2757aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
2758ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t sampleRate = 0;
2759ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t numChannels = 0;
2760ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (freqIndex == 15) {
2761ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        if (csd_size < 5) {
2762ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            return ERROR_MALFORMED;
2763ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
2764aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        sampleRate = br.getBits(24);
2765aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        numChannels = br.getBits(4);
2766ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    } else {
2767595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen        numChannels = br.getBits(4);
276800307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent
276900307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        if (freqIndex == 13 || freqIndex == 14) {
277000307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            return ERROR_MALFORMED;
2771ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
2772ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
277300307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        sampleRate = kSamplingRate[freqIndex];
277400307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent    }
2775595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen
2776f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    if (objectType == AOT_SBR || objectType == AOT_PS) {//SBR specific config per 14496-3 table 1.13
277700307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        uint32_t extFreqIndex = br.getBits(4);
277800307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        int32_t extSampleRate;
277900307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        if (extFreqIndex == 15) {
278000307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            if (csd_size < 8) {
2781595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen                return ERROR_MALFORMED;
2782595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen            }
278300307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            extSampleRate = br.getBits(24);
278400307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        } else {
278500307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            if (extFreqIndex == 13 || extFreqIndex == 14) {
278600307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent                return ERROR_MALFORMED;
278700307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            }
278800307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            extSampleRate = kSamplingRate[extFreqIndex];
2789595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen        }
279000307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        //TODO: save the extension sampling rate value in meta data =>
279100307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        //      mLastTrack->meta->setInt32(kKeyExtSampleRate, extSampleRate);
2792ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2793ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2794f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    switch (numChannels) {
2795f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        // values defined in 14496-3_2009 amendment-4 Table 1.19 - Channel Configuration
2796f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 0:
2797f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 1:// FC
2798f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 2:// FL FR
2799f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 3:// FC, FL FR
2800f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 4:// FC, FL FR, RC
2801f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 5:// FC, FL FR, SL SR
2802f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 6:// FC, FL FR, SL SR, LFE
2803f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            //numChannels already contains the right value
2804f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            break;
2805f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 11:// FC, FL FR, SL SR, RC, LFE
2806f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            numChannels = 7;
2807f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            break;
2808f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 7: // FC, FCL FCR, FL FR, SL SR, LFE
2809f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 12:// FC, FL  FR,  SL SR, RL RR, LFE
2810f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 14:// FC, FL  FR,  SL SR, LFE, FHL FHR
2811f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            numChannels = 8;
2812f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            break;
2813f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        default:
2814f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            return ERROR_UNSUPPORTED;
2815f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    }
2816f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2817f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    {
2818f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        if (objectType == AOT_SBR || objectType == AOT_PS) {
2819f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            objectType = br.getBits(5);
2820f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2821f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            if (objectType == AOT_ESCAPE) {
2822f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                objectType = 32 + br.getBits(6);
2823f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            }
2824f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        }
2825f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        if (objectType == AOT_AAC_LC || objectType == AOT_ER_AAC_LC ||
2826f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                objectType == AOT_ER_AAC_LD || objectType == AOT_ER_AAC_SCAL ||
2827f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                objectType == AOT_ER_BSAC) {
2828f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            const int32_t frameLengthFlag = br.getBits(1);
2829f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2830f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            const int32_t dependsOnCoreCoder = br.getBits(1);
2831f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2832f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            if (dependsOnCoreCoder ) {
2833f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t coreCoderDelay = br.getBits(14);
2834f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            }
2835f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
283645452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            int32_t extensionFlag = -1;
283745452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            if (br.numBitsLeft() > 0) {
283845452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                extensionFlag = br.getBits(1);
283945452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            } else {
284045452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                switch (objectType) {
284145452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                // 14496-3 4.5.1.1 extensionFlag
284245452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_AAC_LC:
284345452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    extensionFlag = 0;
284445452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    break;
284545452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_ER_AAC_LC:
284645452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_ER_AAC_SCAL:
284745452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_ER_BSAC:
284845452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_ER_AAC_LD:
284945452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    extensionFlag = 1;
285045452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    break;
285145452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                default:
285245452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    TRESPASS();
285345452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    break;
285445452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                }
285545452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                ALOGW("csd missing extension flag; assuming %d for object type %u.",
285645452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                        extensionFlag, objectType);
285745452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            }
2858f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
285945452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            if (numChannels == 0) {
2860f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                int32_t channelsEffectiveNum = 0;
2861f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                int32_t channelsNum = 0;
2862f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t ElementInstanceTag = br.getBits(4);
2863f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t Profile = br.getBits(2);
2864f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t SamplingFrequencyIndex = br.getBits(4);
2865f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumFrontChannelElements = br.getBits(4);
2866f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumSideChannelElements = br.getBits(4);
2867f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumBackChannelElements = br.getBits(4);
2868f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumLfeChannelElements = br.getBits(2);
2869f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumAssocDataElements = br.getBits(3);
2870f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumValidCcElements = br.getBits(4);
2871f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2872f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t MonoMixdownPresent = br.getBits(1);
2873f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                if (MonoMixdownPresent != 0) {
2874f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t MonoMixdownElementNumber = br.getBits(4);
2875f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2876f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2877f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t StereoMixdownPresent = br.getBits(1);
2878f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                if (StereoMixdownPresent != 0) {
2879f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t StereoMixdownElementNumber = br.getBits(4);
2880f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2881f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2882f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t MatrixMixdownIndexPresent = br.getBits(1);
2883f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                if (MatrixMixdownIndexPresent != 0) {
2884f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t MatrixMixdownIndex = br.getBits(2);
2885f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t PseudoSurroundEnable = br.getBits(1);
2886f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2887f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2888f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                int i;
2889f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumFrontChannelElements; i++) {
2890f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t FrontElementIsCpe = br.getBits(1);
2891f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t FrontElementTagSelect = br.getBits(4);
2892f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += FrontElementIsCpe ? 2 : 1;
2893f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2894f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2895f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumSideChannelElements; i++) {
2896f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t SideElementIsCpe = br.getBits(1);
2897f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t SideElementTagSelect = br.getBits(4);
2898f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += SideElementIsCpe ? 2 : 1;
2899f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2900f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2901f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumBackChannelElements; i++) {
2902f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t BackElementIsCpe = br.getBits(1);
2903f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t BackElementTagSelect = br.getBits(4);
2904f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += BackElementIsCpe ? 2 : 1;
2905f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2906f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                channelsEffectiveNum = channelsNum;
2907f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2908f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumLfeChannelElements; i++) {
2909f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t LfeElementTagSelect = br.getBits(4);
2910f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += 1;
2911f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2912f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                ALOGV("mpeg4 audio channelsNum = %d", channelsNum);
2913f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                ALOGV("mpeg4 audio channelsEffectiveNum = %d", channelsEffectiveNum);
2914f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                numChannels = channelsNum;
2915f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            }
2916f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        }
2917f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    }
2918f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2919ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (numChannels == 0) {
2920ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_UNSUPPORTED;
2921ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2922ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2923ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevSampleRate;
2924ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
2925ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2926ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevSampleRate != sampleRate) {
29273856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("mpeg4 audio sample rate different from previous setting. "
2928ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevSampleRate, sampleRate);
2929ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2930ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2931ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
2932ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2933ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevChannelCount;
2934ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
2935ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2936ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevChannelCount != numChannels) {
29373856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("mpeg4 audio channel count different from previous setting. "
2938ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevChannelCount, numChannels);
2939ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2940ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2941ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
2942ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2943ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    return OK;
2944ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber}
2945ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
294620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
294720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
294820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::MPEG4Source(
2949942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen        const sp<MPEG4Extractor> &owner,
295020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        const sp<MetaData> &format,
2951693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &dataSource,
295248c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        int32_t timeScale,
295305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const sp<SampleTable> &sampleTable,
295405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        Vector<SidxEntry> &sidx,
2955c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        const Trex *trex,
295605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t firstMoofOffset)
2957942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    : mOwner(owner),
2958942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen      mFormat(format),
295920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDataSource(dataSource),
296048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber      mTimescale(timeScale),
296120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSampleTable(sampleTable),
296220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCurrentSampleIndex(0),
296305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentFragmentIndex(0),
296405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mSegments(sidx),
2965c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen      mTrex(trex),
296605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mFirstMoofOffset(firstMoofOffset),
296705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentMoofOffset(firstMoofOffset),
296805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentTime(0),
2969ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoAllocSize(0),
2970ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoSizes(NULL),
2971ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoOffsetsAllocSize(0),
2972ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoOffsets(NULL),
297320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mIsAVC(false),
29743b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar      mIsHEVC(false),
29756064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber      mNALLengthSize(0),
297620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mStarted(false),
297720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mGroup(NULL),
297820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mBuffer(NULL),
2979dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber      mWantsNALFragments(false),
29800024245e134467d120b40099da16c467dc365e76Andreas Huber      mSrcBuffer(NULL) {
2981ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2982c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    memset(&mTrackFragmentHeaderInfo, 0, sizeof(mTrackFragmentHeaderInfo));
2983c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
2984ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mFormat->findInt32(kKeyCryptoMode, &mCryptoMode);
298548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    mDefaultIVSize = 0;
2986ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mFormat->findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize);
2987ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t keytype;
2988ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    const void *key;
2989ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    size_t keysize;
2990ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mFormat->findData(kKeyCryptoKey, &keytype, &key, &keysize)) {
2991ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        CHECK(keysize <= 16);
2992ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memset(mCryptoKey, 0, 16);
2993ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memcpy(mCryptoKey, key, keysize);
2994ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2995ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
299620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
299720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mFormat->findCString(kKeyMIMEType, &mime);
2998dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(success);
299920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
300018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber    mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
30013b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    mIsHEVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC);
30026064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
30036064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    if (mIsAVC) {
30046064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        uint32_t type;
30056064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const void *data;
30066064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t size;
30076064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(format->findData(kKeyAVCC, &type, &data, &size));
30086064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
30096064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const uint8_t *ptr = (const uint8_t *)data;
30106064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
30116064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(size >= 7);
3012ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
30136064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
30146064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        // The number of bytes used to encode the length of a NAL unit.
30156064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        mNALLengthSize = 1 + (ptr[4] & 3);
30163b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    } else if (mIsHEVC) {
30173b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        uint32_t type;
30183b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        const void *data;
30193b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        size_t size;
30203b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        CHECK(format->findData(kKeyHVCC, &type, &data, &size));
30213b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
30223b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        const uint8_t *ptr = (const uint8_t *)data;
30233b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
30243b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        CHECK(size >= 7);
30253b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
30263b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
30273b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        mNALLengthSize = 1 + (ptr[14 + 7] & 3);
30286064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
302905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
303005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    CHECK(format->findInt32(kKeyTrackID, &mTrackId));
303105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
303205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mFirstMoofOffset != 0) {
303305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t offset = mFirstMoofOffset;
303405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        parseChunk(&offset);
303505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
303620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
303720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
303820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::~MPEG4Source() {
303920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mStarted) {
304020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        stop();
304120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
3042ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    free(mCurrentSampleInfoSizes);
3043ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    free(mCurrentSampleInfoOffsets);
304420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
304520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
304620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::start(MetaData *params) {
30477b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
30487b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
3049dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(!mStarted);
305020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
305120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t val;
3052dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (params && params->findInt32(kKeyWantsNALFragments, &val)
305320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        && val != 0) {
3054dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = true;
305520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    } else {
3056dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = false;
305720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
305820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
305920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = new MediaBufferGroup;
306020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3061738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    int32_t max_size;
3062738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
306320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3064738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    mGroup->add_buffer(new MediaBuffer(max_size));
30650024245e134467d120b40099da16c467dc365e76Andreas Huber
30668da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    mSrcBuffer = new (std::nothrow) uint8_t[max_size];
30678da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    if (mSrcBuffer == NULL) {
30688da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        // file probably specified a bad max size
30698da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        return ERROR_MALFORMED;
30708da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    }
307120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
307220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = true;
307320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
307420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
307520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
307620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
307720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::stop() {
30787b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
30797b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
3080dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
308120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
308220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mBuffer != NULL) {
308320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->release();
308420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
308520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
308620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30870024245e134467d120b40099da16c467dc365e76Andreas Huber    delete[] mSrcBuffer;
30880024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = NULL;
30890024245e134467d120b40099da16c467dc365e76Andreas Huber
309020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    delete mGroup;
309120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = NULL;
309220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
309320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = false;
309420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mCurrentSampleIndex = 0;
309520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
309620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
309720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
309820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
309905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseChunk(off64_t *offset) {
310005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t hdr[2];
310105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
310205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_IO;
310305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
310405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t chunk_size = ntohl(hdr[0]);
310505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t chunk_type = ntohl(hdr[1]);
310605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t data_offset = *offset + 8;
310705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
310805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (chunk_size == 1) {
310905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
311005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_IO;
311105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
311205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        chunk_size = ntoh64(chunk_size);
311305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        data_offset += 8;
311405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
311505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (chunk_size < 16) {
311605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            // The smallest valid chunk is 16 bytes long in this case.
311705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
311805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
311905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (chunk_size < 8) {
312005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // The smallest valid chunk is 8 bytes long.
312105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
312205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
312305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
312405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    char chunk[5];
312505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    MakeFourCCString(chunk_type, chunk);
312605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Source chunk %s @ %llx", chunk, *offset);
312705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
312805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t chunk_data_size = *offset + chunk_size - data_offset;
312905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
313005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    switch(chunk_type) {
313105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
313205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'r', 'a', 'f'):
313305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('m', 'o', 'o', 'f'): {
313405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t stop_offset = *offset + chunk_size;
313505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset = data_offset;
313605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            while (*offset < stop_offset) {
313705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err = parseChunk(offset);
313805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (err != OK) {
313905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return err;
314005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
314105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
314205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
31433f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                // *offset points to the box following this moof. Find the next moof from there.
31443f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen
31453f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                while (true) {
31463f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
31473f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                        return ERROR_END_OF_STREAM;
31483f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    }
31493f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    chunk_size = ntohl(hdr[0]);
31503f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    chunk_type = ntohl(hdr[1]);
31513f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
31523f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                        mNextMoofOffset = *offset;
31533f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                        break;
31543f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    }
31553f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    *offset += chunk_size;
31563f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                }
315705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
315805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
315905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
316005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
316105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'f', 'h', 'd'): {
316205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err;
316305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if ((err = parseTrackFragmentHeader(data_offset, chunk_data_size)) != OK) {
316405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return err;
316505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
316605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                *offset += chunk_size;
316705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                break;
316805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
316905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
317005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'r', 'u', 'n'): {
317105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err;
317205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (mLastParsedTrackId == mTrackId) {
317305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    if ((err = parseTrackFragmentRun(data_offset, chunk_data_size)) != OK) {
317405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        return err;
317505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    }
317605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
317705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
317805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                *offset += chunk_size;
317905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                break;
318005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
318105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3182ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'a', 'i', 'z'): {
3183ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            status_t err;
3184ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((err = parseSampleAuxiliaryInformationSizes(data_offset, chunk_data_size)) != OK) {
3185ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return err;
3186ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3187ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
3188ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
3189ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3190ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'a', 'i', 'o'): {
3191ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            status_t err;
3192ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((err = parseSampleAuxiliaryInformationOffsets(data_offset, chunk_data_size)) != OK) {
3193ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return err;
3194ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3195ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
3196ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
3197ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3198ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3199ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('m', 'd', 'a', 't'): {
3200ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // parse DRM info if present
3201ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("MPEG4Source::parseChunk mdat");
3202ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // if saiz/saoi was previously observed, do something with the sampleinfos
3203ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
3204ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
3205ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3206ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
320705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        default: {
320805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset += chunk_size;
320905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
321005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
321105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
321205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
321305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
321405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
321584333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG4Source::parseSampleAuxiliaryInformationSizes(
321684333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        off64_t offset, off64_t /* size */) {
3217ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("parseSampleAuxiliaryInformationSizes");
3218ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // 14496-12 8.7.12
3219ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t version;
3220ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(
3221ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset, &version, sizeof(version))
3222ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            < (ssize_t)sizeof(version)) {
3223ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3224ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3225ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3226ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (version != 0) {
3227ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_UNSUPPORTED;
3228ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3229ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
3230ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3231ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t flags;
3232ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt24(offset, &flags)) {
3233ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3234ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3235ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 3;
3236ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3237ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (flags & 1) {
3238ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        uint32_t tmp;
3239ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
3240ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_MALFORMED;
3241ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3242ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentAuxInfoType = tmp;
3243ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        offset += 4;
3244ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
3245ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_MALFORMED;
3246ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3247ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentAuxInfoTypeParameter = tmp;
3248ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        offset += 4;
3249ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3250ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3251ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t defsize;
3252ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(offset, &defsize, 1) != 1) {
3253ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_MALFORMED;
3254ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3255ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mCurrentDefaultSampleInfoSize = defsize;
3256ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
3257ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3258ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t smplcnt;
3259ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &smplcnt)) {
3260ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_MALFORMED;
3261ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
326248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    mCurrentSampleInfoCount = smplcnt;
3263ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 4;
3264ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
326548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (mCurrentDefaultSampleInfoSize != 0) {
326648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        ALOGV("@@@@ using default sample info size of %d", mCurrentDefaultSampleInfoSize);
326748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return OK;
326848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
3269ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (smplcnt > mCurrentSampleInfoAllocSize) {
3270ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoSizes = (uint8_t*) realloc(mCurrentSampleInfoSizes, smplcnt);
3271ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoAllocSize = smplcnt;
3272ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3273ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3274ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mDataSource->readAt(offset, mCurrentSampleInfoSizes, smplcnt);
3275ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    return OK;
3276ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen}
3277ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
327884333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(
327984333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        off64_t offset, off64_t /* size */) {
3280ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("parseSampleAuxiliaryInformationOffsets");
3281ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // 14496-12 8.7.13
3282ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t version;
3283ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(offset, &version, sizeof(version)) != 1) {
3284ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3285ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3286ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
3287ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3288ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t flags;
3289ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt24(offset, &flags)) {
3290ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3291ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3292ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 3;
3293ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3294ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t entrycount;
3295ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &entrycount)) {
3296ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3297ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3298ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 4;
3299ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3300ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (entrycount > mCurrentSampleInfoOffsetsAllocSize) {
3301ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoOffsets = (uint64_t*) realloc(mCurrentSampleInfoOffsets, entrycount * 8);
3302ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoOffsetsAllocSize = entrycount;
3303ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3304ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mCurrentSampleInfoOffsetCount = entrycount;
3305ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3306ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < entrycount; i++) {
3307ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (version == 0) {
3308ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t tmp;
3309ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (!mDataSource->getUInt32(offset, &tmp)) {
3310ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
3311ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3312ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mCurrentSampleInfoOffsets[i] = tmp;
3313ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset += 4;
3314ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        } else {
3315ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint64_t tmp;
3316ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (!mDataSource->getUInt64(offset, &tmp)) {
3317ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
3318ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3319ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mCurrentSampleInfoOffsets[i] = tmp;
3320ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset += 8;
3321ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3322ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3323ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3324ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // parse clear/encrypted data
3325ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3326ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    off64_t drmoffset = mCurrentSampleInfoOffsets[0]; // from moof
3327ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3328ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    drmoffset += mCurrentMoofOffset;
3329ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int ivlength;
3330ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    CHECK(mFormat->findInt32(kKeyCryptoDefaultIVSize, &ivlength));
333148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
333248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    // read CencSampleAuxiliaryDataFormats
3333ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mCurrentSampleInfoCount; i++) {
3334ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Sample *smpl = &mCurrentSamples.editItemAt(i);
3335ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3336ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memset(smpl->iv, 0, 16);
3337ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (mDataSource->readAt(drmoffset, smpl->iv, ivlength) != ivlength) {
3338ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_IO;
3339ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3340ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3341ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        drmoffset += ivlength;
3342ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
334348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        int32_t smplinfosize = mCurrentDefaultSampleInfoSize;
334448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        if (smplinfosize == 0) {
334548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smplinfosize = mCurrentSampleInfoSizes[i];
3346ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
334748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        if (smplinfosize > ivlength) {
334848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint16_t numsubsamples;
334948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (!mDataSource->getUInt16(drmoffset, &numsubsamples)) {
3350ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
3351ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3352ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            drmoffset += 2;
335348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            for (size_t j = 0; j < numsubsamples; j++) {
335448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                uint16_t numclear;
335548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                uint32_t numencrypted;
335648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                if (!mDataSource->getUInt16(drmoffset, &numclear)) {
335748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                    return ERROR_IO;
335848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                }
335948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                drmoffset += 2;
336048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                if (!mDataSource->getUInt32(drmoffset, &numencrypted)) {
336148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                    return ERROR_IO;
336248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                }
336348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                drmoffset += 4;
336448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->clearsizes.add(numclear);
336548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->encryptedsizes.add(numencrypted);
3366ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
336748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        } else {
336848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smpl->clearsizes.add(0);
336948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smpl->encryptedsizes.add(smpl->size);
3370ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3371ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3372ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3373ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3374ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    return OK;
3375ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen}
3376ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
337705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentHeader(off64_t offset, off64_t size) {
337805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
337905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 8) {
338005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
338105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
338205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
338305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
3384ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags
338505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
338605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
338705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
338805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & 0xff000000) {
338905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
339005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
339105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
339205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, (uint32_t*)&mLastParsedTrackId)) {
339305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
339405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
339505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
339605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mLastParsedTrackId != mTrackId) {
339705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // this is not the right track, skip it
339805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
339905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
340005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
340105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mFlags = flags;
340205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mTrackID = mLastParsedTrackId;
340305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 8;
340405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 8;
340505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
340605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("fragment header: %08x %08x", flags, mTrackFragmentHeaderInfo.mTrackID);
340705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
340805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent) {
340905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 8) {
341005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
341105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
341205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
341305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset, &mTrackFragmentHeaderInfo.mBaseDataOffset)) {
341405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
341505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
341605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 8;
341705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 8;
341805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
341905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
342005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent) {
342105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
342205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
342305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
342405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
342505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mSampleDescriptionIndex)) {
342605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
342705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
342805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
342905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
343005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
343105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
343205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
343305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
343405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
343505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
343605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
343705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleDuration)) {
343805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
343905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
344005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
344105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
344205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
344305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
344405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
344505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
344605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
344705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
344805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
344905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleSize)) {
345005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
345105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
345205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
345305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
345405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
345505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
345605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
345705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
345805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
345905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
346005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
346105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleFlags)) {
346205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
346305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
346405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
346505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
346605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
346705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
346805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!(flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent)) {
346905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mTrackFragmentHeaderInfo.mBaseDataOffset = mCurrentMoofOffset;
347005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
347105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
347205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mDataOffset = 0;
347305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
347405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
347505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
347605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentRun(off64_t offset, off64_t size) {
347705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
347805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Extractor::parseTrackFragmentRun");
347905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 8) {
348005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
348105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
348205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
348305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    enum {
348405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kDataOffsetPresent                  = 0x01,
348505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kFirstSampleFlagsPresent            = 0x04,
348605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleDurationPresent              = 0x100,
348705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleSizePresent                  = 0x200,
348805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleFlagsPresent                 = 0x400,
348905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleCompositionTimeOffsetPresent = 0x800,
349005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
349105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
349205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
349305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) {
349405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
349505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
349605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("fragment run flags: %08x", flags);
349705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
349805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & 0xff000000) {
349905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
350005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
350105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
350205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if ((flags & kFirstSampleFlagsPresent) && (flags & kSampleFlagsPresent)) {
350305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // These two shall not be used together.
350405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
350505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
350605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
350705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t sampleCount;
350805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, &sampleCount)) {
350905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
351005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
351105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 8;
351205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 8;
351305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
351405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t dataOffset = mTrackFragmentHeaderInfo.mDataOffset;
351505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
351605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t firstSampleFlags = 0;
351705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
351805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kDataOffsetPresent) {
351905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
352005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
352105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
352205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
352305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int32_t dataOffsetDelta;
352405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, (uint32_t*)&dataOffsetDelta)) {
352505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
352605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
352705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
352805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        dataOffset = mTrackFragmentHeaderInfo.mBaseDataOffset + dataOffsetDelta;
352905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
353005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
353105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
353205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
353305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
353405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kFirstSampleFlagsPresent) {
353505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
353605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
353705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
353805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
353905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &firstSampleFlags)) {
354005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
354105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
354205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
354305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
354405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
354505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
354605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t sampleDuration = 0, sampleSize = 0, sampleFlags = 0,
354705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen             sampleCtsOffset = 0;
354805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
354905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size_t bytesPerSample = 0;
355005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleDurationPresent) {
355105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
355205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
355305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
355405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration;
3555c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    } else if (mTrex) {
3556c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        sampleDuration = mTrex->default_sample_duration;
355705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
355805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
355905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleSizePresent) {
356005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
356105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
356205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
356305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
356405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
356505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
356605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
356705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
356805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleFlagsPresent) {
356905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
357005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
357105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
357205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
357305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
357405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
357505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
357605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
357705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleCompositionTimeOffsetPresent) {
357805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
357905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
358005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleCtsOffset = 0;
358105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
358205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3583a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    if (size < (off64_t)sampleCount * bytesPerSample) {
358405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
358505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
358605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
358705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Sample tmp;
358805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    for (uint32_t i = 0; i < sampleCount; ++i) {
358905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleDurationPresent) {
359005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleDuration)) {
359105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
359205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
359305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
359405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
359505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
359605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleSizePresent) {
359705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleSize)) {
359805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
359905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
360005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
360105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
360205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
360305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleFlagsPresent) {
360405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleFlags)) {
360505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
360605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
360705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
360805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
360905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
361005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleCompositionTimeOffsetPresent) {
361105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleCtsOffset)) {
361205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
361305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
361405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
361505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
361605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3617a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("adding sample %d at offset 0x%08" PRIx64 ", size %u, duration %u, "
3618ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen              " flags 0x%08x", i + 1,
361905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dataOffset, sampleSize, sampleDuration,
362005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                (flags & kFirstSampleFlagsPresent) && i == 0
362105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ? firstSampleFlags : sampleFlags);
362205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.offset = dataOffset;
362305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.size = sampleSize;
362405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.duration = sampleDuration;
3625c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        tmp.compositionOffset = sampleCtsOffset;
362605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentSamples.add(tmp);
362705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
362805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        dataOffset += sampleSize;
362905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
363005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
363105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mDataOffset = dataOffset;
363205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
363305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
363405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
363505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
363620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> MPEG4Source::getFormat() {
36377b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
36387b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
363920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return mFormat;
364020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
364120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36426064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const {
36436064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    switch (mNALLengthSize) {
36446064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 1:
36456064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return *data;
36466064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 2:
36476064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U16_AT(data);
36486064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 3:
36496064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return ((size_t)data[0] << 16) | U16_AT(&data[1]);
36506064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 4:
36516064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U32_AT(data);
36526064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
36536064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
36546064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // This cannot happen, mNALLengthSize springs to life by adding 1 to
36556064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // a 2-bit integer.
36566064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    CHECK(!"Should not be here.");
36576064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
36586064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    return 0;
36596064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber}
36606064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
366120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::read(
366220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
36637b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
36647b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
3665dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
366620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
366705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mFirstMoofOffset > 0) {
366805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return fragmentedRead(out, options);
366905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
367005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
367120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *out = NULL;
367220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3673abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    int64_t targetSampleTimeUs = -1;
3674abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
367520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t seekTimeUs;
3676abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
3677abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
3678abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t findFlags = 0;
3679abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        switch (mode) {
3680abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_PREVIOUS_SYNC:
3681abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagBefore;
3682abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3683abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_NEXT_SYNC:
3684abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagAfter;
3685abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3686abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST_SYNC:
3687abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST:
3688abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagClosest;
3689abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3690abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            default:
3691abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                CHECK(!"Should not be here.");
3692abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3693abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3694abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
369520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        uint32_t sampleIndex;
3696abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        status_t err = mSampleTable->findSampleAtTime(
3697599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar                seekTimeUs, 1000000, mTimescale,
3698abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                &sampleIndex, findFlags);
3699abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3700abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
3701abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // We found the closest sample already, now we want the sync
3702abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // sample preceding it (or the sample itself of course), even
3703abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // if the subsequent sync sample is closer.
3704abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            findFlags = SampleTable::kFlagBefore;
3705abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3706abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3707abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleIndex;
3708abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (err == OK) {
3709abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            err = mSampleTable->findSyncSampleNear(
3710abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    sampleIndex, &syncSampleIndex, findFlags);
3711abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
371220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3713788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        uint32_t sampleTime;
3714788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        if (err == OK) {
3715788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber            err = mSampleTable->getMetaDataForSample(
3716788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber                    sampleIndex, NULL, NULL, &sampleTime);
3717788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        }
3718788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber
371920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (err != OK) {
37205295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            if (err == ERROR_OUT_OF_RANGE) {
37215295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // An attempt to seek past the end of the stream would
37225295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // normally cause this ERROR_OUT_OF_RANGE error. Propagating
37235295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // this all the way to the MediaPlayer would cause abnormal
37245295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // termination. Legacy behaviour appears to be to behave as if
37255295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // we had seeked to the end of stream, ending normally.
37265295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                err = ERROR_END_OF_STREAM;
37275295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            }
372805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("end of stream");
372920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return err;
373020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
373120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3732abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
3733abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
3734abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3735abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3736abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#if 0
3737abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleTime;
3738abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
3739abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    syncSampleIndex, NULL, NULL, &syncSampleTime));
3740abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3741df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("seek to time %lld us => sample at time %lld us, "
3742abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             "sync sample at time %lld us",
3743abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             seekTimeUs,
3744abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             sampleTime * 1000000ll / mTimescale,
3745abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             syncSampleTime * 1000000ll / mTimescale);
3746abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#endif
3747abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3748abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        mCurrentSampleIndex = syncSampleIndex;
374920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mBuffer != NULL) {
375020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
375120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
375220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
375320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
375420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // fall through
375520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
375620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3757c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset;
37580024245e134467d120b40099da16c467dc365e76Andreas Huber    size_t size;
3759170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih    uint32_t cts, stts;
37608bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    bool isSyncSample;
3761dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool newBuffer = false;
3762dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (mBuffer == NULL) {
3763dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        newBuffer = true;
376420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3765c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        status_t err =
3766c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber            mSampleTable->getMetaDataForSample(
3767170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                    mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample, &stts);
376820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3769dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
3770dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
3771dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3772dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3773dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        err = mGroup->acquire_buffer(&mBuffer);
3774c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
3775dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
3776ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            CHECK(mBuffer == NULL);
3777dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
3778dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
37790024245e134467d120b40099da16c467dc365e76Andreas Huber    }
378020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37813b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    if ((!mIsAVC && !mIsHEVC) || mWantsNALFragments) {
3782dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (newBuffer) {
3783dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ssize_t num_bytes_read =
378434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
3785dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3786dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            if (num_bytes_read < (ssize_t)size) {
3787dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer->release();
3788dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer = NULL;
3789dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3790dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                return ERROR_IO;
3791dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            }
3792dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
37937b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber            CHECK(mBuffer != NULL);
3794dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->set_range(0, size);
3795dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->meta_data()->clear();
379648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mBuffer->meta_data()->setInt64(
37974678a6dc5f09008481524949a9667af5a6190374Andreas Huber                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
3798170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih            mBuffer->meta_data()->setInt64(
3799170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                    kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
3800abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3801abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            if (targetSampleTimeUs >= 0) {
3802abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                mBuffer->meta_data()->setInt64(
3803abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                        kKeyTargetTime, targetSampleTimeUs);
3804abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            }
3805abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
38068bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            if (isSyncSample) {
38078bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
38088bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            }
38098bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
3810dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ++mCurrentSampleIndex;
3811dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3812dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
38133b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        if (!mIsAVC && !mIsHEVC) {
3814dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            *out = mBuffer;
3815dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
3816dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3817dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return OK;
3818dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3819dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3820dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Each NAL unit is split up into its constituent fragments and
3821dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // each one of them returned in its own buffer.
3822dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
38236064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(mBuffer->range_length() >= mNALLengthSize);
3824dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3825dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        const uint8_t *src =
3826dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
3827dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
38286064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t nal_size = parseNALSize(src);
3829e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
383029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("incomplete NAL unit.");
3831e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3832e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer->release();
3833e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer = NULL;
3834e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3835e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            return ERROR_MALFORMED;
3836e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        }
3837dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3838dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        MediaBuffer *clone = mBuffer->clone();
38397b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(clone != NULL);
38406064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
3841dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
38427b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(mBuffer != NULL);
3843dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mBuffer->set_range(
38446064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_offset() + mNALLengthSize + nal_size,
38456064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_length() - mNALLengthSize - nal_size);
3846dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3847dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (mBuffer->range_length() == 0) {
3848dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->release();
3849dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
3850dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3851dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3852dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        *out = clone;
3853dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3854dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        return OK;
3855dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    } else {
3856dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Whole NAL units are returned but each fragment is prefixed by
3857dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // the start code (0x00 00 00 01).
3858dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        ssize_t num_bytes_read = 0;
3859dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        int32_t drm = 0;
3860dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
3861dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (usesDRM) {
3862dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            num_bytes_read =
3863dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
3864dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
3865dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
3866dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
386720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
386820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (num_bytes_read < (ssize_t)size) {
386920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
387020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
387120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3872dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return ERROR_IO;
387320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
387420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3875dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (usesDRM) {
3876dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK(mBuffer != NULL);
3877dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            mBuffer->set_range(0, size);
38786064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
3879dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
3880dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            uint8_t *dstData = (uint8_t *)mBuffer->data();
3881dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size_t srcOffset = 0;
3882dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size_t dstOffset = 0;
3883e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3884dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            while (srcOffset < size) {
388534fe252c89e33572d01fea981b58d7b115e76164James Dong                bool isMalFormed = (srcOffset + mNALLengthSize > size);
388634fe252c89e33572d01fea981b58d7b115e76164James Dong                size_t nalLength = 0;
388734fe252c89e33572d01fea981b58d7b115e76164James Dong                if (!isMalFormed) {
388834fe252c89e33572d01fea981b58d7b115e76164James Dong                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
388934fe252c89e33572d01fea981b58d7b115e76164James Dong                    srcOffset += mNALLengthSize;
389034fe252c89e33572d01fea981b58d7b115e76164James Dong                    isMalFormed = srcOffset + nalLength > size;
389134fe252c89e33572d01fea981b58d7b115e76164James Dong                }
3892e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
389334fe252c89e33572d01fea981b58d7b115e76164James Dong                if (isMalFormed) {
389429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                    ALOGE("Video is malformed");
3895dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    mBuffer->release();
3896dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    mBuffer = NULL;
3897dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return ERROR_MALFORMED;
3898dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
3899dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
3900dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                if (nalLength == 0) {
3901dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    continue;
3902dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
3903dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3904dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                CHECK(dstOffset + 4 <= mBuffer->size());
3905dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3906dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3907dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3908dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3909dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 1;
3910dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
3911dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                srcOffset += nalLength;
3912dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstOffset += nalLength;
3913dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
3914dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK_EQ(srcOffset, size);
3915dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK(mBuffer != NULL);
3916dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            mBuffer->set_range(0, dstOffset);
3917dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3918dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
391920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->meta_data()->clear();
392048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        mBuffer->meta_data()->setInt64(
39214678a6dc5f09008481524949a9667af5a6190374Andreas Huber                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
3922170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih        mBuffer->meta_data()->setInt64(
3923170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
3924abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3925abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (targetSampleTimeUs >= 0) {
3926abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            mBuffer->meta_data()->setInt64(
3927abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    kKeyTargetTime, targetSampleTimeUs);
3928abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3929abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
39308bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        if (isSyncSample) {
39318bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
39328bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        }
39338bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
393420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        ++mCurrentSampleIndex;
393520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
393620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        *out = mBuffer;
393720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
393820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
393920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
394020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
394120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
394220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
394305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::fragmentedRead(
394405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MediaBuffer **out, const ReadOptions *options) {
394505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
394605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Source::fragmentedRead");
394705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
394805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    CHECK(mStarted);
394905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
395005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    *out = NULL;
395105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
395205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t targetSampleTimeUs = -1;
395305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
395405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t seekTimeUs;
395505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ReadOptions::SeekMode mode;
395605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
395705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
395805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int numSidxEntries = mSegments.size();
395905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (numSidxEntries != 0) {
396005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            int64_t totalTime = 0;
396105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t totalOffset = mFirstMoofOffset;
396205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            for (int i = 0; i < numSidxEntries; i++) {
396305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                const SidxEntry *se = &mSegments[i];
396405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (totalTime + se->mDurationUs > seekTimeUs) {
396505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    // The requested time is somewhere in this segment
39663f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    if ((mode == ReadOptions::SEEK_NEXT_SYNC && seekTimeUs > totalTime) ||
396705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        (mode == ReadOptions::SEEK_CLOSEST_SYNC &&
396805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        (seekTimeUs - totalTime) > (totalTime + se->mDurationUs - seekTimeUs))) {
396905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        // requested next sync, or closest sync and it was closer to the end of
397005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        // this segment
397105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        totalTime += se->mDurationUs;
397205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        totalOffset += se->mSize;
397305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    }
397405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    break;
397505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
397605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                totalTime += se->mDurationUs;
397705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                totalOffset += se->mSize;
397805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
3979ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentMoofOffset = totalOffset;
3980ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSamples.clear();
3981ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSampleIndex = 0;
3982ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            parseChunk(&totalOffset);
3983ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentTime = totalTime * mTimescale / 1000000ll;
3984ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen        } else {
3985ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            // without sidx boxes, we can only seek to 0
3986ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentMoofOffset = mFirstMoofOffset;
3987ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSamples.clear();
3988ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSampleIndex = 0;
3989ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            off64_t tmp = mCurrentMoofOffset;
3990ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            parseChunk(&tmp);
3991ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentTime = 0;
399205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
399305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
399405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer != NULL) {
399505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
399605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
399705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
399805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
399905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // fall through
400005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
400105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
400205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t offset = 0;
4003442cc6dc48f8188e097617f7f804c314a9dacd0eAndreas Huber    size_t size = 0;
400405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t cts = 0;
400505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    bool isSyncSample = false;
400605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    bool newBuffer = false;
400705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mBuffer == NULL) {
400805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        newBuffer = true;
400905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
401005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mCurrentSampleIndex >= mCurrentSamples.size()) {
40113f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            // move to next fragment if there is one
40123f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            if (mNextMoofOffset <= mCurrentMoofOffset) {
40133f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                return ERROR_END_OF_STREAM;
40143f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            }
4015ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            off64_t nextMoof = mNextMoofOffset;
401605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentMoofOffset = nextMoof;
401705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentSamples.clear();
401805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentSampleIndex = 0;
401905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            parseChunk(&nextMoof);
4020ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            if (mCurrentSampleIndex >= mCurrentSamples.size()) {
4021ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen                return ERROR_END_OF_STREAM;
4022ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            }
402305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
402405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
402505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
402605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset = smpl->offset;
402705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size = smpl->size;
4028c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        cts = mCurrentTime + smpl->compositionOffset;
402905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentTime += smpl->duration;
403005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        isSyncSample = (mCurrentSampleIndex == 0); // XXX
403105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
403205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        status_t err = mGroup->acquire_buffer(&mBuffer);
403305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
403405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (err != OK) {
403505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer == NULL);
403605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("acquire_buffer returned %d", err);
403705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return err;
403805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
403905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
404005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
404148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
404248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    const sp<MetaData> bufmeta = mBuffer->meta_data();
404348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    bufmeta->clear();
404448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (smpl->encryptedsizes.size()) {
404548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // store clear/encrypted lengths in metadata
404648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyPlainSizes, 0,
404748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->clearsizes.array(), smpl->clearsizes.size() * 4);
404848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyEncryptedSizes, 0,
404948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
405048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
405148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
405248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setInt32(kKeyCryptoMode, mCryptoMode);
405348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16);
405448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
405548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
40563b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    if ((!mIsAVC && !mIsHEVC)|| mWantsNALFragments) {
405705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (newBuffer) {
405805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ssize_t num_bytes_read =
405905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
406005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
406105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (num_bytes_read < (ssize_t)size) {
406205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->release();
406305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer = NULL;
406405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
406505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                ALOGV("i/o error");
406605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_IO;
406705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
406805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
406905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
407005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, size);
407105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt64(
407205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
4073170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih            mBuffer->meta_data()->setInt64(
4074170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                    kKeyDuration, ((int64_t)smpl->duration * 1000000) / mTimescale);
407505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
407605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (targetSampleTimeUs >= 0) {
407705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->meta_data()->setInt64(
407805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        kKeyTargetTime, targetSampleTimeUs);
407905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
408005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
408105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (isSyncSample) {
408205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
408305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
408405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
408505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ++mCurrentSampleIndex;
408605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
408705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
40883b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        if (!mIsAVC && !mIsHEVC) {
408905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *out = mBuffer;
409005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
409105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
409205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return OK;
409305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
409405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
409505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // Each NAL unit is split up into its constituent fragments and
409605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // each one of them returned in its own buffer.
409705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
409805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(mBuffer->range_length() >= mNALLengthSize);
409905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
410005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const uint8_t *src =
410105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
410205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
410305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size_t nal_size = parseNALSize(src);
410405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
410505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGE("incomplete NAL unit.");
410605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
410705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
410805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
410905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
411005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
411105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
411205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
411305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MediaBuffer *clone = mBuffer->clone();
411405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(clone != NULL);
411505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
411605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
411705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(mBuffer != NULL);
411805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer->set_range(
411905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->range_offset() + mNALLengthSize + nal_size,
412005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->range_length() - mNALLengthSize - nal_size);
412105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
412205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer->range_length() == 0) {
412305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
412405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
412505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
412605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
412705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        *out = clone;
412805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
412905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
413005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
413105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV("whole NAL");
413205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // Whole NAL units are returned but each fragment is prefixed by
413305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // the start code (0x00 00 00 01).
413405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ssize_t num_bytes_read = 0;
413505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int32_t drm = 0;
413605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
413705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (usesDRM) {
413805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            num_bytes_read =
413905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
414005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else {
414105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
414205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
414305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
414405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (num_bytes_read < (ssize_t)size) {
414505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
414605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
414705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
414805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("i/o error");
414905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_IO;
415005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
415105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
415205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (usesDRM) {
415305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
415405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, size);
415505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
415605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else {
415705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            uint8_t *dstData = (uint8_t *)mBuffer->data();
415805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            size_t srcOffset = 0;
415905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            size_t dstOffset = 0;
416005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
416105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            while (srcOffset < size) {
416205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                bool isMalFormed = (srcOffset + mNALLengthSize > size);
416305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                size_t nalLength = 0;
416405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (!isMalFormed) {
416505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
416605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    srcOffset += mNALLengthSize;
416705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    isMalFormed = srcOffset + nalLength > size;
416805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
416905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
417005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (isMalFormed) {
417105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ALOGE("Video is malformed");
417205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    mBuffer->release();
417305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    mBuffer = NULL;
417405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return ERROR_MALFORMED;
417505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
417605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
417705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (nalLength == 0) {
417805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    continue;
417905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
418005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
418105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                CHECK(dstOffset + 4 <= mBuffer->size());
418205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
418305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
418405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
418505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
418605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 1;
418705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
418805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                srcOffset += nalLength;
418905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstOffset += nalLength;
419005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
419105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK_EQ(srcOffset, size);
419205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
419305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, dstOffset);
419405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
419505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
419605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer->meta_data()->setInt64(
419705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
4198170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih        mBuffer->meta_data()->setInt64(
4199170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                kKeyDuration, ((int64_t)smpl->duration * 1000000) / mTimescale);
420005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
420105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (targetSampleTimeUs >= 0) {
420205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt64(
420305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    kKeyTargetTime, targetSampleTimeUs);
420405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
420505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
420605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (isSyncSample) {
420705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
420805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
420905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
421005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ++mCurrentSampleIndex;
421105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
421205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        *out = mBuffer;
421305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer = NULL;
421405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
421505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
421605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
421705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
421805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
4219bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas HuberMPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix(
4220bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        const char *mimePrefix) {
4221bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    for (Track *track = mFirstTrack; track != NULL; track = track->next) {
4222bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        const char *mime;
4223bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        if (track->meta != NULL
4224bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                && track->meta->findCString(kKeyMIMEType, &mime)
4225bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) {
4226bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber            return track;
4227bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        }
4228bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    }
4229bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber
4230bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    return NULL;
4231bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber}
4232bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber
42331b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool LegacySniffMPEG4(
4234693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
423520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[8];
423620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
423734769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    ssize_t n = source->readAt(4, header, sizeof(header));
423820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (n < (ssize_t)sizeof(header)) {
423920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return false;
424020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
424120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
424220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
4243b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8)
4244b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8)
42450dba73763a04d39faf999dcc5ef12af3c99535a7Andreas Huber        || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
4246ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
4247983b449a27b5fa91eca82ede5204b4341899be62Andreas Huber        || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
424818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
42495a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        *confidence = 0.4;
425020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
425120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return true;
425220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
425320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
425420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return false;
425520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
425620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
42571b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool isCompatibleBrand(uint32_t fourcc) {
42581b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    static const uint32_t kCompatibleBrands[] = {
42591b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', 'm'),
42601b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', '2'),
42611b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('a', 'v', 'c', '1'),
42623b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        FOURCC('h', 'v', 'c', '1'),
42633b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        FOURCC('h', 'e', 'v', '1'),
42641b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('3', 'g', 'p', '4'),
42651b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '1'),
42661b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '2'),
42674cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong
42684cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        // Won't promise that the following file types can be played.
42694cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        // Just give these file types a chance.
42704cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        FOURCC('q', 't', ' ', ' '),  // Apple's QuickTime
42714cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        FOURCC('M', 'S', 'N', 'V'),  // Sony's PSP
427258fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber
427358fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber        FOURCC('3', 'g', '2', 'a'),  // 3GPP2
427458fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber        FOURCC('3', 'g', '2', 'b'),
42751b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    };
42761b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
42771b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    for (size_t i = 0;
42781b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]);
42791b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         ++i) {
42801b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        if (kCompatibleBrands[i] == fourcc) {
42811b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            return true;
42821b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
42831b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
42841b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
42851b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
42861b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
42871b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
42881b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// Attempt to actually parse the 'ftyp' atom and determine if a suitable
42891b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// compatible brand is present.
4290a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// Also try to identify where this file's metadata ends
4291a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// (end of the 'moov' atom) and report it to the caller as part of
4292a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// the metadata.
42931b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool BetterSniffMPEG4(
4294a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
4295a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        sp<AMessage> *meta) {
4296a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    // We scan up to 128 bytes to identify this file as an MP4.
4297a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    static const off64_t kMaxScanOffset = 128ll;
42981b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4299a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    off64_t offset = 0ll;
4300a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    bool foundGoodFileType = false;
4301a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    off64_t moovAtomEndOffset = -1ll;
4302a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    bool done = false;
43031b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4304a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    while (!done && offset < kMaxScanOffset) {
4305a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint32_t hdr[2];
4306a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        if (source->readAt(offset, hdr, 8) < 8) {
4307a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            return false;
4308a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        }
4309a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4310a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint64_t chunkSize = ntohl(hdr[0]);
4311a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint32_t chunkType = ntohl(hdr[1]);
4312a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        off64_t chunkDataOffset = offset + 8;
4313a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4314a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        if (chunkSize == 1) {
4315a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            if (source->readAt(offset + 8, &chunkSize, 8) < 8) {
43161b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                return false;
43171b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
43181b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4319a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            chunkSize = ntoh64(chunkSize);
4320a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            chunkDataOffset += 8;
4321a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4322a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            if (chunkSize < 16) {
4323a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                // The smallest valid chunk is 16 bytes long in this case.
4324a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                return false;
4325a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            }
4326a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        } else if (chunkSize < 8) {
4327a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            // The smallest valid chunk is 8 bytes long.
4328a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            return false;
4329a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        }
4330a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4331a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        off64_t chunkDataSize = offset + chunkSize - chunkDataOffset;
4332a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
433305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        char chunkstring[5];
433405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MakeFourCCString(chunkType, chunkstring);
4335a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("saw chunk type %s, size %" PRIu64 " @ %lld", chunkstring, chunkSize, offset);
4336a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        switch (chunkType) {
4337a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            case FOURCC('f', 't', 'y', 'p'):
4338a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            {
4339a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                if (chunkDataSize < 8) {
4340a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    return false;
4341a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
4342a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4343a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4;
4344a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
4345a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (i == 1) {
4346a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        // Skip this index, it refers to the minorVersion,
4347a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        // not a brand.
4348a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        continue;
4349a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
4350a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4351a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    uint32_t brand;
4352a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (source->readAt(
4353a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                                chunkDataOffset + 4 * i, &brand, 4) < 4) {
4354a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        return false;
4355a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
4356a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4357a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    brand = ntohl(brand);
4358a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4359a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (isCompatibleBrand(brand)) {
4360a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        foundGoodFileType = true;
4361a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        break;
4362a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
4363a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
4364a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4365a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                if (!foundGoodFileType) {
4366a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    return false;
4367a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
4368a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
43691b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                break;
43701b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
4371a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4372a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            case FOURCC('m', 'o', 'o', 'v'):
4373a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            {
4374a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                moovAtomEndOffset = offset + chunkSize;
4375a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4376a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                done = true;
4377a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                break;
4378a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            }
4379a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4380a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            default:
4381a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                break;
43821b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
4383a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4384a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        offset += chunkSize;
43851b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
43861b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4387a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (!foundGoodFileType) {
43881b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return false;
43891b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
43901b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
43911b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
43925a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber    *confidence = 0.4f;
43931b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4394a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (moovAtomEndOffset >= 0) {
4395a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        *meta = new AMessage;
4396a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        (*meta)->setInt64("meta-data-size", moovAtomEndOffset);
4397a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4398456caf3f5f0af673dc120c17c23635f40d8f5ac2Andreas Huber        ALOGV("found metadata size: %lld", moovAtomEndOffset);
4399a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    }
4400a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
44011b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return true;
44021b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
44031b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
44041b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberbool SniffMPEG4(
44055a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
4406a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        sp<AMessage> *meta) {
4407a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (BetterSniffMPEG4(source, mimeType, confidence, meta)) {
44081b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
44091b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
44101b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
44111b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    if (LegacySniffMPEG4(source, mimeType, confidence)) {
44125ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Identified supported mpeg4 through LegacySniffMPEG4.");
44131b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
44141b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
44151b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
44161b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
44171b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
44181b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
441920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
4420