MPEG4Extractor.cpp revision e3e82d54c51a3130badcd9e433fe808d965f15c2
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
268b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampestatic const bool kUseHexDump = false;
269b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe
27020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatic void hexdump(const void *_data, size_t size) {
27120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const uint8_t *data = (const uint8_t *)_data;
27220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t offset = 0;
27320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (offset < size) {
274377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        printf("0x%04zx  ", offset);
27520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        size_t n = size - offset;
27720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (n > 16) {
27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            n = 16;
27920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
28020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < 16; ++i) {
28220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (i == 8) {
28320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(" ");
28420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (offset + i < size) {
28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%02x ", data[offset + i]);
28820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("   ");
29020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf(" ");
29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < n; ++i) {
29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (isprint(data[offset + i])) {
29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%c", data[offset + i]);
29820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
29920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(".");
30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
30120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
30220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf("\n");
30420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        offset += 16;
30620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
30720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
30820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huberstatic const char *FourCC2MIME(uint32_t fourcc) {
31020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch (fourcc) {
31120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
31218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AAC;
31320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
31518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_NB;
31620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
317371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
31818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_WB;
319371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
32020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
32118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_MPEG4;
32220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
324e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('h', '2', '6', '3'):
325e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('H', '2', '6', '3'):
32618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_H263;
32720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
32918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_AVC;
33020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3313b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'v', 'c', '1'):
3323b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'e', 'v', '1'):
3333b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            return MEDIA_MIMETYPE_VIDEO_HEVC;
33420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
335dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(!"should not be here.");
33620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
33720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
33820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
33920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
34048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissenstatic bool AdjustChannelsAndRate(uint32_t fourcc, uint32_t *channels, uint32_t *rate) {
34148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, FourCC2MIME(fourcc))) {
34248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // AMR NB audio is always mono, 8kHz
34348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *channels = 1;
34448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *rate = 8000;
34548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return true;
34648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, FourCC2MIME(fourcc))) {
34748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // AMR WB audio is always mono, 16kHz
34848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *channels = 1;
34948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *rate = 16000;
35048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return true;
35148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
35248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    return false;
35348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen}
35448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
355693d271e62a3726689ff68f4505ba49228eb94b2Andreas HuberMPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
356c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    : mMoofOffset(0),
357928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang      mMoofFound(false),
358928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang      mMdatFound(false),
35905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mDataSource(source),
360bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber      mInitCheck(NO_INIT),
3617be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber      mHasVideo(false),
362fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen      mHeaderTimescale(0),
36320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mFirstTrack(NULL),
36472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber      mLastTrack(NULL),
365dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mFileMetaData(new MetaData),
366dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mFirstSINF(NULL),
367dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mIsDrm(false) {
36820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
36920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Extractor::~MPEG4Extractor() {
37120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
37220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        Track *next = track->next;
37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete track;
37620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = next;
37720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
37820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFirstTrack = mLastTrack = NULL;
379dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
380dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    SINF *sinf = mFirstSINF;
381dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (sinf) {
382dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        SINF *next = sinf->next;
3838da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        delete[] sinf->IPMPData;
384dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        delete sinf;
385dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf = next;
386dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
387dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    mFirstSINF = NULL;
388ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
389ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mPssh.size(); i++) {
390ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        delete [] mPssh[i].data;
391ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
39220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
39320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
39405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenuint32_t MPEG4Extractor::flags() const {
39505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return CAN_PAUSE |
39605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ((mMoofOffset == 0 || mSidxEntries.size() != 0) ?
39705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    (CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK) : 0);
39805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
39905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
4007be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Hubersp<MetaData> MPEG4Extractor::getMetaData() {
4017be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    status_t err;
4027be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    if ((err = readMetaData()) != OK) {
40372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return new MetaData;
4047be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    }
4057be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
40672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return mFileMetaData;
4077be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber}
4087be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
409693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersize_t MPEG4Extractor::countTracks() {
41020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
41120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
412ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        ALOGV("MPEG4Extractor::countTracks: no tracks");
413693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return 0;
41420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
41520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
416693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    size_t n = 0;
41720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
41820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
419693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        ++n;
42020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
42120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
42220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
423a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("MPEG4Extractor::countTracks: %zu tracks", n);
424693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    return n;
42520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
42620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4277e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Hubersp<MetaData> MPEG4Extractor::getTrackMetaData(
4287e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        size_t index, uint32_t flags) {
42920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
43020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
43120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return NULL;
43220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
43320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
43520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
43720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
43820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
43920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
44020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
44120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
44220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
44320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
444371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
445371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
446371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
447371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
4487e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    if ((flags & kIncludeExtensiveMetaData)
4497e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            && !track->includes_expensive_metadata) {
4507e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        track->includes_expensive_metadata = true;
4517e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
4527e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        const char *mime;
4537e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        CHECK(track->meta->findCString(kKeyMIMEType, &mime));
4547e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        if (!strncasecmp("video/", mime, 6)) {
45505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (mMoofOffset > 0) {
45605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                int64_t duration;
45705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (track->meta->findInt64(kKeyDuration, &duration)) {
45805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    // nothing fancy, just pick a frame near 1/4th of the duration
45905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    track->meta->setInt64(
46005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            kKeyThumbnailTime, duration / 4);
46105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
46205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            } else {
46305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t sampleIndex;
46405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t sampleTime;
46505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK
46605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        && track->sampleTable->getMetaDataForSample(
46705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            sampleIndex, NULL /* offset */, NULL /* size */,
46805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            &sampleTime) == OK) {
46905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    track->meta->setInt64(
47005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            kKeyThumbnailTime,
47105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            ((int64_t)sampleTime * 1000000) / track->timescale);
47205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
4737e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            }
4747e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        }
4757e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    }
4767e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
47720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return track->meta;
47820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
47920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
48048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissenstatic void MakeFourCCString(uint32_t x, char *s) {
48148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[0] = x >> 24;
48248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[1] = (x >> 16) & 0xff;
48348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[2] = (x >> 8) & 0xff;
48448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[3] = x & 0xff;
48548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[4] = '\0';
48648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen}
48748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
48820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Extractor::readMetaData() {
489bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    if (mInitCheck != NO_INIT) {
490bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        return mInitCheck;
49120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
49220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
493c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = 0;
49420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
495928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang    bool sawMoovOrSidx = false;
496928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang
497928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang    while (!(sawMoovOrSidx && (mMdatFound || mMoofFound))) {
498a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen        off64_t orig_offset = offset;
49905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        err = parseChunk(&offset, 0);
500a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen
5014ff2a0dbb178c4ea652f30aa4f1d3deb9fdbc832Lajos Molnar        if (err != OK && err != UNKNOWN_ERROR) {
5024ff2a0dbb178c4ea652f30aa4f1d3deb9fdbc832Lajos Molnar            break;
5034ff2a0dbb178c4ea652f30aa4f1d3deb9fdbc832Lajos Molnar        } else if (offset <= orig_offset) {
504a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            // only continue parsing if the offset was advanced,
505a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            // otherwise we might end up in an infinite loop
506a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            ALOGE("did not advance: 0x%lld->0x%lld", orig_offset, offset);
507a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            err = ERROR_MALFORMED;
508a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            break;
509928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang        } else if (err == UNKNOWN_ERROR) {
510928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang            sawMoovOrSidx = true;
51105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
51220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
5137be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
514bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    if (mInitCheck == OK) {
51572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        if (mHasVideo) {
516bc8b5faec8a0a9ad7c8d94945e7b000d63f0afe6Andreas Huber            mFileMetaData->setCString(
517bc8b5faec8a0a9ad7c8d94945e7b000d63f0afe6Andreas Huber                    kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG4);
51872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else {
51972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
52072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
521bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    } else {
522bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        mInitCheck = err;
52320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
52420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
525bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    CHECK_NE(err, (status_t)NO_INIT);
526ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
527ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // copy pssh data into file metadata
528ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int psshsize = 0;
529ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mPssh.size(); i++) {
530ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        psshsize += 20 + mPssh[i].datalen;
531ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
532ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (psshsize) {
533ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        char *buf = (char*)malloc(psshsize);
534ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        char *ptr = buf;
535ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        for (size_t i = 0; i < mPssh.size(); i++) {
536ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memcpy(ptr, mPssh[i].uuid, 20); // uuid + length
537ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memcpy(ptr + 20, mPssh[i].data, mPssh[i].datalen);
538ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ptr += (20 + mPssh[i].datalen);
539ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
540ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mFileMetaData->setData(kKeyPssh, 'pssh', buf, psshsize);
541ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        free(buf);
542ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
543bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    return mInitCheck;
54420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
54520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
546dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wangchar* MPEG4Extractor::getDrmTrackInfo(size_t trackID, int *len) {
547dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mFirstSINF == NULL) {
548dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return NULL;
549dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
550dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
551dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    SINF *sinf = mFirstSINF;
552dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (sinf && (trackID != sinf->trackID)) {
553dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf = sinf->next;
554dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
555dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
556dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (sinf == NULL) {
557dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return NULL;
558dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
559dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
560dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    *len = sinf->len;
561dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return sinf->IPMPData;
562dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
563dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
564dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang// Reads an encoded integer 7 bits at a time until it encounters the high bit clear.
56556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenstatic int32_t readSize(off64_t offset,
566dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        const sp<DataSource> DataSource, uint8_t *numOfBytes) {
567dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint32_t size = 0;
568dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t data;
569dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    bool moreData = true;
570dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    *numOfBytes = 0;
571dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
572dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (moreData) {
573dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (DataSource->readAt(offset, &data, 1) < 1) {
574dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return -1;
575dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
576dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        offset ++;
577dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        moreData = (data >= 128) ? true : false;
578dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        size = (size << 7) | (data & 0x7f); // Take last 7 bits
579dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        (*numOfBytes) ++;
580dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
581dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
582dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return size;
583dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
584dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
58584333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG4Extractor::parseDrmSINF(
58684333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        off64_t * /* offset */, off64_t data_offset) {
587dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t updateIdTag;
588dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
589dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
590dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
591dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset ++;
592dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
593dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (0x01/*OBJECT_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
594dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
595dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
596dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
597dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t numOfBytes;
598dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    int32_t size = readSize(data_offset, mDataSource, &numOfBytes);
599dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size < 0) {
600dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
601dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
602dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset += numOfBytes;
603dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
604dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while(size >= 11 ) {
605dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t descriptorTag;
606dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, &descriptorTag, 1) < 1) {
607dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
608dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
609dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset ++;
610dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
611dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (0x11/*OBJECT_DESCRIPTOR_ID_TAG*/ != descriptorTag) {
612dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
613dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
614dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
615dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t buffer[8];
616dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        //ObjectDescriptorID and ObjectDescriptor url flag
617dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, buffer, 2) < 2) {
618dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
619dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
620dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset += 2;
621dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
622dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if ((buffer[1] >> 5) & 0x0001) { //url flag is set
623dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
624dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
625dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
626dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, buffer, 8) < 8) {
627dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
628dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
629dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset += 8;
630dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
631dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if ((0x0F/*ES_ID_REF_TAG*/ != buffer[1])
632dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                || ( 0x0A/*IPMP_DESCRIPTOR_POINTER_ID_TAG*/ != buffer[5])) {
633dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
634dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
635dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
636dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        SINF *sinf = new SINF;
637dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->trackID = U16_AT(&buffer[3]);
638dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->IPMPDescriptorID = buffer[7];
639dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->next = mFirstSINF;
640dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        mFirstSINF = sinf;
641dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
642dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        size -= (8 + 2 + 1);
643dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
644dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
645dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size != 0) {
646dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
647dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
648dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
649dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
650dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
651dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
652dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset ++;
653dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
654dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if(0x05/*IPMP_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
655dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
656dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
657dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
658dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    size = readSize(data_offset, mDataSource, &numOfBytes);
659dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size < 0) {
660dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
661dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
662dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset += numOfBytes;
663dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
664dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (size > 0) {
665dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t tag;
666dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        int32_t dataLen;
667dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, &tag, 1) < 1) {
668dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
669dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
670dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset ++;
671dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
672dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (0x0B/*IPMP_DESCRIPTOR_ID_TAG*/ == tag) {
673dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            uint8_t id;
674dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            dataLen = readSize(data_offset, mDataSource, &numOfBytes);
675dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (dataLen < 0) {
676dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
677dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            } else if (dataLen < 4) {
678dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
679dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
680dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset += numOfBytes;
681dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
682dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (mDataSource->readAt(data_offset, &id, 1) < 1) {
683dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
684dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
685dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset ++;
686dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
687dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            SINF *sinf = mFirstSINF;
688dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            while (sinf && (sinf->IPMPDescriptorID != id)) {
689dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                sinf = sinf->next;
690dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
691dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (sinf == NULL) {
692dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
693dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
694dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            sinf->len = dataLen - 3;
6958da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            sinf->IPMPData = new (std::nothrow) char[sinf->len];
6968da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            if (sinf->IPMPData == NULL) {
6978da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen                return ERROR_MALFORMED;
6988da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            }
699f7df9ab3187a3c02bffe1fba10d3fb95197e4a07Ichitaro Kohara            data_offset += 2;
700dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
701f7df9ab3187a3c02bffe1fba10d3fb95197e4a07Ichitaro Kohara            if (mDataSource->readAt(data_offset, sinf->IPMPData, sinf->len) < sinf->len) {
702dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
703dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
704dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset += sinf->len;
705dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
706dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size -= (dataLen + numOfBytes + 1);
707dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
708dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
709dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
710dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size != 0) {
711dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
712dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
713dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
714dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return UNKNOWN_ERROR;  // Return a dummy error.
715dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
716dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
71772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstruct PathAdder {
71872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder(Vector<uint32_t> *path, uint32_t chunkType)
71972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        : mPath(path) {
72072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        mPath->push(chunkType);
72172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
72272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
72372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    ~PathAdder() {
72472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        mPath->pop();
72572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
72672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
72772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberprivate:
72872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    Vector<uint32_t> *mPath;
72972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
73072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder(const PathAdder &);
73172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder &operator=(const PathAdder &);
73272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber};
73372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
73472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic bool underMetaDataPath(const Vector<uint32_t> &path) {
73572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return path.size() >= 5
73672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[0] == FOURCC('m', 'o', 'o', 'v')
73772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[1] == FOURCC('u', 'd', 't', 'a')
73872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[2] == FOURCC('m', 'e', 't', 'a')
73972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[3] == FOURCC('i', 'l', 's', 't');
74072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
74172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
74272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber// Given a time in seconds since Jan 1 1904, produce a human-readable string.
74372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic void convertTimeToDate(int64_t time_1904, String8 *s) {
74472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    time_t time_1970 = time_1904 - (((66 * 365 + 17) * 24) * 3600);
74572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
74672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    char tmp[32];
74772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", gmtime(&time_1970));
74872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
74972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    s->setTo(tmp);
75072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
75172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
752c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
7535d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    ALOGV("entering parseChunk %lld/%d", *offset, depth);
75420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t hdr[2];
75534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
75620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_IO;
75720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
75820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint64_t chunk_size = ntohl(hdr[0]);
7592d0ac425564ff9882ebaac5267d1a04d4af67d00Bernhard Rosenkränzer    int32_t chunk_type = ntohl(hdr[1]);
760c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t data_offset = *offset + 8;
76120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
76220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (chunk_size == 1) {
76334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_IO;
76520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        chunk_size = ntoh64(chunk_size);
76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        data_offset += 8;
76871b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber
76971b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        if (chunk_size < 16) {
77071b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber            // The smallest valid chunk is 16 bytes long in this case.
77171b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber            return ERROR_MALFORMED;
77271b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        }
773a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen    } else if (chunk_size == 0) {
774a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen        if (depth == 0) {
775a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            // atom extends to end of file
776a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            off64_t sourceSize;
777a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            if (mDataSource->getSize(&sourceSize) == OK) {
778a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen                chunk_size = (sourceSize - *offset);
779a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            } else {
780a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen                // XXX could we just pick a "sufficiently large" value here?
781a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen                ALOGE("atom size is 0, and data source has no size");
782a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen                return ERROR_MALFORMED;
783a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            }
784a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen        } else {
785a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            // not allowed for non-toplevel atoms, skip it
786a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            *offset += 4;
787a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            return OK;
788a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen        }
78971b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber    } else if (chunk_size < 8) {
79071b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        // The smallest valid chunk is 8 bytes long.
791a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGE("invalid chunk size: %" PRIu64, chunk_size);
79271b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        return ERROR_MALFORMED;
79320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
79420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
79520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    char chunk[5];
79620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MakeFourCCString(chunk_type, chunk);
79705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("chunk: %s @ %lld, %d", chunk, *offset, depth);
79820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
799b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    if (kUseHexDump) {
800b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        static const char kWhitespace[] = "                                        ";
801b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
802b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        printf("%sfound chunk '%s' of size %" PRIu64 "\n", indent, chunk, chunk_size);
80320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
804b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        char buffer[256];
805b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        size_t n = chunk_size;
806b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        if (n > sizeof(buffer)) {
807b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe            n = sizeof(buffer);
808b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        }
809b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        if (mDataSource->readAt(*offset, buffer, n)
810b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                < (ssize_t)n) {
811b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe            return ERROR_IO;
812b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        }
813ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
814b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        hexdump(buffer, n);
815b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    }
81620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
81772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder autoAdder(&mPath, chunk_type);
81872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
819c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t chunk_data_size = *offset + chunk_size - data_offset;
82020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
82172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (chunk_type != FOURCC('c', 'p', 'r', 't')
822515e855eae78aa495da58356486aaa666cb57fd1James Dong            && chunk_type != FOURCC('c', 'o', 'v', 'r')
82372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            && mPath.size() == 5 && underMetaDataPath(mPath)) {
824c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t stop_offset = *offset + chunk_size;
82572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        *offset = data_offset;
82672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        while (*offset < stop_offset) {
82772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            status_t err = parseChunk(offset, depth + 1);
82872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (err != OK) {
82972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return err;
83072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
83172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
832bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
833bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (*offset != stop_offset) {
834bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
835bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
83672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
83772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return OK;
83872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
83972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
84020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch(chunk_type) {
84120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'v'):
84220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'k'):
84320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'i', 'a'):
84420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'i', 'n', 'f'):
84520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('d', 'i', 'n', 'f'):
84620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'b', 'l'):
84720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'v', 'e', 'x'):
84820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'f'):
84920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'f'):
85020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'f', 'r', 'a'):
85172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('u', 'd', 't', 'a'):
85272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('i', 'l', 's', 't'):
853ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'i', 'n', 'f'):
854ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'c', 'h', 'i'):
8550a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        case FOURCC('e', 'd', 't', 's'):
85620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
857928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang            if (chunk_type == FOURCC('m', 'o', 'o', 'f') && !mMoofFound) {
858928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang                // store the offset of the first segment
859928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang                mMoofFound = true;
860928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang                mMoofOffset = *offset;
861928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang            }
862928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang
86350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
864a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                ALOGV("sampleTable chunk is %" PRIu64 " bytes long.", chunk_size);
86550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
866b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                if (mDataSource->flags()
867b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                        & (DataSource::kWantsPrefetching
868b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                            | DataSource::kIsCachingDataSource)) {
86950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    sp<MPEG4DataSource> cachedSource =
87050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                        new MPEG4DataSource(mDataSource);
87150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
87250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
87350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                        mDataSource = cachedSource;
87450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    }
87550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                }
8761edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber
877f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                if (mLastTrack == NULL)
878f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                    return ERROR_MALFORMED;
879f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
8801edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber                mLastTrack->sampleTable = new SampleTable(mDataSource);
88150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            }
88250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
8836f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber            bool isTrack = false;
884bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (chunk_type == FOURCC('t', 'r', 'a', 'k')) {
8856f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                isTrack = true;
8866f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
887bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                Track *track = new Track;
888bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->next = NULL;
889bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                if (mLastTrack) {
890bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    mLastTrack->next = track;
891bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                } else {
892bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    mFirstTrack = track;
893bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                }
894bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                mLastTrack = track;
895bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
896bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->meta = new MetaData;
897bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->includes_expensive_metadata = false;
8986f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                track->skipTrack = false;
899bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->timescale = 0;
900bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->meta->setCString(kKeyMIMEType, "application/octet-stream");
901bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
902bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
903c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
90420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset;
90520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
90620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
90720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
90820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
90920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
91020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
91120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
912bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
913bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
914bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
915bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
9166f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber            if (isTrack) {
9176f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                if (mLastTrack->skipTrack) {
9186f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    Track *cur = mFirstTrack;
9196f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
9206f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    if (cur == mLastTrack) {
9216f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        delete cur;
9226f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        mFirstTrack = mLastTrack = NULL;
9236f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    } else {
9246f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        while (cur && cur->next != mLastTrack) {
9256f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                            cur = cur->next;
9266f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        }
9276f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        cur->next = NULL;
9286f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        delete mLastTrack;
9296f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        mLastTrack = cur;
9306f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    }
9316f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
9326f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    return OK;
9336f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                }
9346f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
935bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                status_t err = verifyTrack(mLastTrack);
936bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
937bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                if (err != OK) {
938bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    return err;
939bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                }
940bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
941bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                mInitCheck = OK;
94220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
943dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                if (!mIsDrm) {
944dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return UNKNOWN_ERROR;  // Return a dummy error.
945dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                } else {
946dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return OK;
947dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
94820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
94920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
95020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
95120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9520a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        case FOURCC('e', 'l', 's', 't'):
9530a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        {
9540517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
9550517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
9560a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            // See 14496-12 8.6.6
9570a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            uint8_t version;
9580a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (mDataSource->readAt(data_offset, &version, 1) < 1) {
9590a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                return ERROR_IO;
9600a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
9610a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9620a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            uint32_t entry_count;
9630a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (!mDataSource->getUInt32(data_offset + 4, &entry_count)) {
9640a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                return ERROR_IO;
9650a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
9660a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9670a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (entry_count != 1) {
9680a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                // we only support a single entry at the moment, for gapless playback
9690a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                ALOGW("ignoring edit list with %d entries", entry_count);
970fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            } else if (mHeaderTimescale == 0) {
971210efd48ed21ca0084d9440f9a1db7d9878f8094Marco Nelissen                ALOGW("ignoring edit list because timescale is 0");
9720a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            } else {
9730a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                off64_t entriesoffset = data_offset + 8;
9740a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                uint64_t segment_duration;
9750a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int64_t media_time;
9760a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9770a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                if (version == 1) {
9780a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    if (!mDataSource->getUInt64(entriesoffset, &segment_duration) ||
9790a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                            !mDataSource->getUInt64(entriesoffset + 8, (uint64_t*)&media_time)) {
9800a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        return ERROR_IO;
9810a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    }
9820a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                } else if (version == 0) {
9830a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    uint32_t sd;
9840a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int32_t mt;
9850a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    if (!mDataSource->getUInt32(entriesoffset, &sd) ||
9860a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                            !mDataSource->getUInt32(entriesoffset + 4, (uint32_t*)&mt)) {
9870a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        return ERROR_IO;
9880a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    }
9890a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    segment_duration = sd;
9900a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    media_time = mt;
9910a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                } else {
9920a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    return ERROR_IO;
9930a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                }
9940a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
995fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                uint64_t halfscale = mHeaderTimescale / 2;
996fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                segment_duration = (segment_duration * 1000000 + halfscale)/ mHeaderTimescale;
997fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                media_time = (media_time * 1000000 + halfscale) / mHeaderTimescale;
9980a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9990a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int64_t duration;
10000a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int32_t samplerate;
10011391f933b49cfb56da9aa63f723de83b076cf888Robert Shih                if (!mLastTrack) {
10021391f933b49cfb56da9aa63f723de83b076cf888Robert Shih                    return ERROR_MALFORMED;
10031391f933b49cfb56da9aa63f723de83b076cf888Robert Shih                }
10040a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                if (mLastTrack->meta->findInt64(kKeyDuration, &duration) &&
10050a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        mLastTrack->meta->findInt32(kKeySampleRate, &samplerate)) {
10060a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
10070a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t delay = (media_time  * samplerate + 500000) / 1000000;
10080a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
10090a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
10100a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t paddingus = duration - (segment_duration + media_time);
1011465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                    if (paddingus < 0) {
1012465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        // track duration from media header (which is what kKeyDuration is) might
1013465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        // be slightly shorter than the segment duration, which would make the
1014465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        // padding negative. Clamp to zero.
1015465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        paddingus = 0;
1016465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                    }
10170a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t paddingsamples = (paddingus * samplerate + 500000) / 1000000;
10180a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    mLastTrack->meta->setInt32(kKeyEncoderPadding, paddingsamples);
10190a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                }
10200a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
10210a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            break;
10220a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        }
10230a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
1024ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('f', 'r', 'm', 'a'):
1025ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
10260517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
10270517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
102848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t original_fourcc;
1029ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset, &original_fourcc, 4) < 4) {
1030ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1031ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1032ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            original_fourcc = ntohl(original_fourcc);
1033ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("read original format: %d", original_fourcc);
1034f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
1035f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1036f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1037f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
1038ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc));
103948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t num_channels = 0;
104048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t sample_rate = 0;
104148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (AdjustChannelsAndRate(original_fourcc, &num_channels, &sample_rate)) {
104248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
104348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
104448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            }
1045ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1046ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1047ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1048ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('t', 'e', 'n', 'c'):
1049ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
10500517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
10510517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1052ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (chunk_size < 32) {
1053ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1054ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1055ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1056ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // tenc box contains 1 byte version, 3 byte flags, 3 byte default algorithm id, one byte
1057ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // default IV size, 16 bytes default KeyID
1058ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // (ISO 23001-7)
1059ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            char buf[4];
1060ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memset(buf, 0, 4);
1061ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 4, buf + 1, 3) < 3) {
1062ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1063ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1064ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t defaultAlgorithmId = ntohl(*((int32_t*)buf));
1065ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (defaultAlgorithmId > 1) {
1066ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only 0 (clear) and 1 (AES-128) are valid
1067ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1068ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1069ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1070ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memset(buf, 0, 4);
1071ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 7, buf + 3, 1) < 1) {
1072ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1073ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1074ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t defaultIVSize = ntohl(*((int32_t*)buf));
1075ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1076ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((defaultAlgorithmId == 0 && defaultIVSize != 0) ||
1077ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    (defaultAlgorithmId != 0 && defaultIVSize == 0)) {
1078ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only unencrypted data must have 0 IV size
1079ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1080ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            } else if (defaultIVSize != 0 &&
1081ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    defaultIVSize != 8 &&
1082ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    defaultIVSize != 16) {
1083ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only supported sizes are 0, 8 and 16
1084ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1085ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1086ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1087ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint8_t defaultKeyId[16];
1088ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1089ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 8, &defaultKeyId, 16) < 16) {
1090ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1091ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1092ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1093f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1094f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1095f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
1096ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setInt32(kKeyCryptoMode, defaultAlgorithmId);
1097ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setInt32(kKeyCryptoDefaultIVSize, defaultIVSize);
1098ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setData(kKeyCryptoKey, 'tenc', defaultKeyId, 16);
1099ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1100ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1101ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
110220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'k', 'h', 'd'):
110320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
11040517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
11050517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1106ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            status_t err;
1107ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) {
1108ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber                return err;
110920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
111020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
111120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
111220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
111320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1114ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('p', 's', 's', 'h'):
1115ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
11160517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
11170517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1118ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            PsshInfo pssh;
1119ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1120ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 4, &pssh.uuid, 16) < 16) {
1121ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1122ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1123ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1124ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t psshdatalen = 0;
1125ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 20, &psshdatalen, 4) < 4) {
1126ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1127ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1128ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            pssh.datalen = ntohl(psshdatalen);
1129ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("pssh data size: %d", pssh.datalen);
1130ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (pssh.datalen + 20 > chunk_size) {
1131ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // pssh data length exceeds size of containing box
1132ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1133ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1134ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
11358da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            pssh.data = new (std::nothrow) uint8_t[pssh.datalen];
11368da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            if (pssh.data == NULL) {
11378da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen                return ERROR_MALFORMED;
11388da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            }
1139ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("allocated pssh @ %p", pssh.data);
1140ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ssize_t requested = (ssize_t) pssh.datalen;
1141ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 24, pssh.data, requested) < requested) {
1142ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1143ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1144ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mPssh.push_back(pssh);
1145ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1146ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1147ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1148ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
114920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'h', 'd'):
115020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
11510517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
11520517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1153202fbed96db40ec5fb43d633fc97601a15a6dd7aRobert Shih            if (chunk_data_size < 4 || mLastTrack == NULL) {
115420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
115520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
115620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
115720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t version;
115834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
115920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, &version, sizeof(version))
116020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(version)) {
116120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
116220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
116320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1164c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t timescale_offset;
116520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
116620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
116720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 16;
116820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else if (version == 0) {
116920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 8;
117020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
117120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
117220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
117320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
117420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t timescale;
117534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
117620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        timescale_offset, &timescale, sizeof(timescale))
117720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(timescale)) {
117820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
117920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
118120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->timescale = ntohl(timescale);
118220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1183c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            // 14496-12 says all ones means indeterminate, but some files seem to use
1184c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            // 0 instead. We treat both the same.
118505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            int64_t duration = 0;
118620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
118734769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
118820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration, sizeof(duration))
118920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration)) {
119020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
119120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
1192c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (duration != -1) {
1193c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    duration = ntoh64(duration);
1194c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
119520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
119605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t duration32;
119734769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
119820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration32, sizeof(duration32))
119920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration32)) {
120020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
120120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
120205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (duration32 != 0xffffffff) {
120305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    duration = ntohl(duration32);
120405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
120520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1206e3e82d54c51a3130badcd9e433fe808d965f15c2Joshua J. Drake            if (duration != 0 && mLastTrack->timescale != 0) {
1207c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mLastTrack->meta->setInt64(
1208c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                        kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
1209c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
121020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12117a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            uint8_t lang[2];
12127a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            off64_t lang_offset;
12137a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            if (version == 1) {
12147a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                lang_offset = timescale_offset + 4 + 8;
12157a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            } else if (version == 0) {
12167a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                lang_offset = timescale_offset + 4 + 4;
12177a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            } else {
12187a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                return ERROR_IO;
12197a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            }
12207a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
12217a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            if (mDataSource->readAt(lang_offset, &lang, sizeof(lang))
12227a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                    < (ssize_t)sizeof(lang)) {
12237a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                return ERROR_IO;
12247a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            }
12257a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
12267a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // To get the ISO-639-2/T three character language code
12277a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // 1 bit pad followed by 3 5-bits characters. Each character
12287a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // is packed as the difference between its ASCII value and 0x60.
12297a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            char lang_code[4];
12307a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[0] = ((lang[0] >> 2) & 0x1f) + 0x60;
12317a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[1] = ((lang[0] & 0x3) << 3 | (lang[1] >> 5)) + 0x60;
12327a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[2] = (lang[1] & 0x1f) + 0x60;
12337a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[3] = '\0';
12347a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
12357a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            mLastTrack->meta->setCString(
12367a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                    kKeyMediaLanguage, lang_code);
12377a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
123820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
123920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
124020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
124120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'd'):
124220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
124320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 8) {
124420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
124520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
124620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
124720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8];
1248c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size < (off64_t)sizeof(buffer)) {
1249bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1250bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
1251bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
125234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
125320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, 8) < 8) {
125420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
125520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
125620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
125720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
125820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
125920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
126020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
126120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
126220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t entry_count = U32_AT(&buffer[4]);
126320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
126420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (entry_count > 1) {
12653b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // For 3GPP timed text, there could be multiple tx3g boxes contain
12663b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // multiple text display formats. These formats will be used to
12673b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // display the timed text.
1268ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // For encrypted files, there may also be more than one entry.
12693b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                const char *mime;
1270f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
1271f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                if (mLastTrack == NULL)
1272f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                    return ERROR_MALFORMED;
1273f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
12743b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1275ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) &&
1276ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                        strcasecmp(mime, "application/octet-stream")) {
12773b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    // For now we only support a single type of media per track.
12783b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    mLastTrack->skipTrack = true;
12793b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    *offset += chunk_size;
12803b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    break;
12813b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                }
128220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1283c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
128420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + 8;
128520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            for (uint32_t i = 0; i < entry_count; ++i) {
128620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
128720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
128820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
128920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
129020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1291bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1292bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1293bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1294bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
129520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
129620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
129720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
129820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
129948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        case FOURCC('e', 'n', 'c', 'a'):
130020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
1301371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
130220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
130320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8 + 20];
130420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
130520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic AudioSampleEntry size.
130620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
130720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
130820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
130934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
131020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
131120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
131220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
131320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1314b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe            uint16_t data_ref_index __unused = U16_AT(&buffer[6]);
131548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t num_channels = U16_AT(&buffer[16]);
131620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
131781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint16_t sample_size = U16_AT(&buffer[18]);
131881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
131981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
1320f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1321f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1322f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
132348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (chunk_type != FOURCC('e', 'n', 'c', 'a')) {
132448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                // if the chunk type is enca, we'll get the type from the sinf/frma box later
132548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
132648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate);
132720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
132848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            ALOGV("*** coding='%s' %d channels, size %d, rate %d\n",
132981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                   chunk, num_channels, sample_size, sample_rate);
133020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
133120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
133220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1333c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
133420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
133520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
133620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
133720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
133820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
133920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
134020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1341bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1342bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1343bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1344bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
134520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
134620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
134720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
134820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
1349ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('e', 'n', 'c', 'v'):
135020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
1351e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('H', '2', '6', '3'):
1352e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('h', '2', '6', '3'):
135320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
13543b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'v', 'c', '1'):
13553b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'e', 'v', '1'):
135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
13577be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber            mHasVideo = true;
13587be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
135920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[78];
136020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
136120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic VideoSampleEntry size.
136220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
136320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
136420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
136534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
136620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
136720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
136820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
136920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1370b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe            uint16_t data_ref_index __unused = U16_AT(&buffer[6]);
137120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t width = U16_AT(&buffer[6 + 18]);
137220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t height = U16_AT(&buffer[6 + 20]);
137320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1374ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // The video sample is not standard-compliant if it has invalid dimension.
1375a6256238d9015c42129fe43791968768fe501efaJames Dong            // Use some default width and height value, and
1376a6256238d9015c42129fe43791968768fe501efaJames Dong            // let the decoder figure out the actual width and height (and thus
1377a6256238d9015c42129fe43791968768fe501efaJames Dong            // be prepared for INFO_FOMRAT_CHANGED event).
1378a6256238d9015c42129fe43791968768fe501efaJames Dong            if (width == 0)  width  = 352;
1379a6256238d9015c42129fe43791968768fe501efaJames Dong            if (height == 0) height = 288;
1380a6256238d9015c42129fe43791968768fe501efaJames Dong
1381134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            // printf("*** coding='%s' width=%d height=%d\n",
1382134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            //        chunk, width, height);
138320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1384f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1385f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1386f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
1387ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (chunk_type != FOURCC('e', 'n', 'c', 'v')) {
1388ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // if the chunk type is encv, we'll get the type from the sinf/frma box later
1389ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
1390ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
139120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyWidth, width);
139220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyHeight, height);
139320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1394c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
139520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
139620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
139720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
139820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
139920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
140020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
140120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1402bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1403bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1404bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1405bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
140620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
140720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
140820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
140920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'c', 'o'):
141020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('c', 'o', '6', '4'):
141120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1412274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
1413274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake                return ERROR_MALFORMED;
1414274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake
141520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
141620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setChunkOffsetParams(
141720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
141820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14190517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
14200517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
142120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
142220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
142320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
142420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
142520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
142620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
142720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
142820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'c'):
142920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1430274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
1431274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake                return ERROR_MALFORMED;
1432274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake
143320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
143420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleToChunkParams(
143520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
143620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14370517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
14380517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
143920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
144020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
144120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
144220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
144320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
144420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
144520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
144620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'z'):
144720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'z', '2'):
144820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1449274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
1450274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake                return ERROR_MALFORMED;
1451274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake
145220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
145320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleSizeParams(
145420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
145520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14560517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
14570517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
145820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
145920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
146020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
146120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1462738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            size_t max_size;
146349110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            err = mLastTrack->sampleTable->getMaxSampleSize(&max_size);
146449110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber
146549110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            if (err != OK) {
146649110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber                return err;
146749110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            }
1468738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber
146905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (max_size != 0) {
147005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // Assume that a given buffer only contains at most 10 chunks,
147105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // each chunk originally prefixed with a 2 byte length will
147205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
147305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // and thus will grow by 2 bytes per chunk.
147405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
147505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            } else {
147605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // No size was specified. Pick a conservatively large size.
147705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                int32_t width, height;
1478f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                if (!mLastTrack->meta->findInt32(kKeyWidth, &width) ||
1479f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    !mLastTrack->meta->findInt32(kKeyHeight, &height)) {
148005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ALOGE("No width or height, assuming worst case 1080p");
1481f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    width = 1920;
1482f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    height = 1080;
148305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
1484f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar
14854256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen                const char *mime;
14864256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1487f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
1488f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // AVC requires compression ratio of at least 2, and uses
1489f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // macroblocks
1490f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    max_size = ((width + 15) / 16) * ((height + 15) / 16) * 192;
1491f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                } else {
1492f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // For all other formats there is no minimum compression
1493f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // ratio. Use compression ratio of 1.
1494f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    max_size = width * height * 3 / 2;
149505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
1496f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size);
149705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
1498113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong
14994256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            // NOTE: setting another piece of metadata invalidates any pointers (such as the
15004256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            // mimetype) previously obtained, so don't cache them.
1501113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            const char *mime;
1502113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1503113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            // Calculate average frame rate.
1504113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            if (!strncasecmp("video/", mime, 6)) {
1505113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                size_t nSamples = mLastTrack->sampleTable->countSamples();
1506113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                int64_t durationUs;
1507113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                if (mLastTrack->meta->findInt64(kKeyDuration, &durationUs)) {
1508113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                    if (durationUs > 0) {
1509113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                        int32_t frameRate = (nSamples * 1000000LL +
1510113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                                    (durationUs >> 1)) / durationUs;
1511113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                        mLastTrack->meta->setInt32(kKeyFrameRate, frameRate);
1512113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                    }
1513113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                }
1514113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            }
1515113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong
151620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
151720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
151820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
151920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 't', 's'):
152020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1521274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
1522274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake                return ERROR_MALFORMED;
1523274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake
15240517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
15250517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
152620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
152720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setTimeToSampleParams(
152820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
152920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
153020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
153120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
153220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
153320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
153420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
153520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
153620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15374931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        case FOURCC('c', 't', 't', 's'):
15384931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        {
1539274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
1540274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake                return ERROR_MALFORMED;
1541274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake
15420517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
15430517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
15444931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            status_t err =
15454931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                mLastTrack->sampleTable->setCompositionTimeToSampleParams(
15464931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                        data_offset, chunk_data_size);
15474931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
15484931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            if (err != OK) {
15494931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                return err;
15504931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            }
15514931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
15524931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            break;
15534931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        }
15544931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
155520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 's'):
155620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1557274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
1558274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake                return ERROR_MALFORMED;
1559274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake
15600517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
15610517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
156220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
156320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSyncSampleParams(
156420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
156520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
156620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
156720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
156820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
156920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
157020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
157120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
157220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1573e1b2ccf317301af42bb4b6631a3bcd7d8f519d00Chih-Hung Hsieh        // �xyz
1574e1b2ccf317301af42bb4b6631a3bcd7d8f519d00Chih-Hung Hsieh        case FOURCC(0xA9, 'x', 'y', 'z'):
15754948818cb91176df74c972ac27b2f392b5d148bcJames Dong        {
15760517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
15770517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1578e1b2ccf317301af42bb4b6631a3bcd7d8f519d00Chih-Hung Hsieh            // Best case the total data length inside "�xyz" box
1579e1b2ccf317301af42bb4b6631a3bcd7d8f519d00Chih-Hung Hsieh            // would be 8, for instance "�xyz" + "\x00\x04\x15\xc7" + "0+0/",
15804948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // where "\x00\x04" is the text string length with value = 4,
15814948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // "\0x15\xc7" is the language code = en, and "0+0" is a
15824948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // location (string) value with longitude = 0 and latitude = 0.
15834948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (chunk_data_size < 8) {
15844948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_MALFORMED;
15854948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
15864948818cb91176df74c972ac27b2f392b5d148bcJames Dong
15874948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Worst case the location string length would be 18,
15884948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // for instance +90.0000-180.0000, without the trailing "/" and
15894948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // the string length + language code.
15904948818cb91176df74c972ac27b2f392b5d148bcJames Dong            char buffer[18];
15914948818cb91176df74c972ac27b2f392b5d148bcJames Dong
15924948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Substracting 5 from the data size is because the text string length +
15934948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // language code takes 4 bytes, and the trailing slash "/" takes 1 byte.
15944948818cb91176df74c972ac27b2f392b5d148bcJames Dong            off64_t location_length = chunk_data_size - 5;
15954948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (location_length >= (off64_t) sizeof(buffer)) {
15964948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_MALFORMED;
15974948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
15984948818cb91176df74c972ac27b2f392b5d148bcJames Dong
15994948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (mDataSource->readAt(
16004948818cb91176df74c972ac27b2f392b5d148bcJames Dong                        data_offset + 4, buffer, location_length) < location_length) {
16014948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_IO;
16024948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
16034948818cb91176df74c972ac27b2f392b5d148bcJames Dong
16044948818cb91176df74c972ac27b2f392b5d148bcJames Dong            buffer[location_length] = '\0';
16054948818cb91176df74c972ac27b2f392b5d148bcJames Dong            mFileMetaData->setCString(kKeyLocation, buffer);
16064948818cb91176df74c972ac27b2f392b5d148bcJames Dong            break;
16074948818cb91176df74c972ac27b2f392b5d148bcJames Dong        }
16084948818cb91176df74c972ac27b2f392b5d148bcJames Dong
160920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('e', 's', 'd', 's'):
161020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
16110517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
16120517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
161320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
161420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
161520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
161620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
161720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[256];
1618c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size > (off64_t)sizeof(buffer)) {
161920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
162020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
162120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
162234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
162320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
162420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
162520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
162620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
162720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
162820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
162920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
163020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
163120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1632f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1633f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1634f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
163520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
163620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
163720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1638ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            if (mPath.size() >= 2
1639ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
1640ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // Information from the ESDS must be relied on for proper
1641ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // setup of sample rate and channel count for MPEG4 Audio.
1642ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // The generic header appears to only contain generic
1643ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // information...
1644ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1645ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio(
1646ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                        &buffer[4], chunk_data_size - 4);
1647ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1648ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                if (err != OK) {
1649ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    return err;
1650ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                }
1651ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            }
1652ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
165320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
165420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
165520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
165620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', 'C'):
165720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
16580517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
16590517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1660d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson            sp<ABuffer> buffer = new ABuffer(chunk_data_size);
166120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
166234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
1663d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson                        data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
166420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
166520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
166620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1667f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1668f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1669f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
167020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
1671d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson                    kKeyAVCC, kTypeAVCC, buffer->data(), chunk_data_size);
167220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
167320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
167420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
16753b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'v', 'c', 'C'):
16763b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        {
16773b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            sp<ABuffer> buffer = new ABuffer(chunk_data_size);
16783b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
16793b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            if (mDataSource->readAt(
16803b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar                        data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
16813b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar                return ERROR_IO;
16823b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            }
16833b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
1684f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1685f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1686f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
16873b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            mLastTrack->meta->setData(
16883b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar                    kKeyHVCC, kTypeHVCC, buffer->data(), chunk_data_size);
16893b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
16903b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            *offset += chunk_size;
16913b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            break;
16923b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        }
169320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1694244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        case FOURCC('d', '2', '6', '3'):
1695244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        {
16960517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
169717e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            /*
169817e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * d263 contains a fixed 7 bytes part:
169917e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   vendor - 4 bytes
170017e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   version - 1 byte
170117e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   level - 1 byte
170217e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   profile - 1 byte
170317e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * optionally, "d263" box itself may contain a 16-byte
170417e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * bit rate box (bitr)
170517e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   average bit rate - 4 bytes
170617e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   max bit rate - 4 bytes
170717e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             */
170817e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            char buffer[23];
170917e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            if (chunk_data_size != 7 &&
171017e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong                chunk_data_size != 23) {
171129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Incorrect D263 box size %lld", chunk_data_size);
1712244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                return ERROR_MALFORMED;
1713244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            }
1714244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1715244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            if (mDataSource->readAt(
1716244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                    data_offset, buffer, chunk_data_size) < chunk_data_size) {
1717244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                return ERROR_IO;
1718244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            }
1719244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1720f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1721f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1722f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
1723244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size);
1724244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1725244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            break;
1726244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        }
1727244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
172872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'e', 't', 'a'):
172972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
173072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            uint8_t buffer[4];
1731c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size < (off64_t)sizeof(buffer)) {
17320517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen                *offset += chunk_size;
1733bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1734bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
1735bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
173672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
173772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, buffer, 4) < 4) {
17380517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen                *offset += chunk_size;
173972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
174072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
174172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
174272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (U32_AT(buffer) != 0) {
174372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                // Should be version 0, flags 0.
1744ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
1745ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // If it's not, let's assume this is one of those
1746ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // apparently malformed chunks that don't have flags
1747ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // and completely different semantics than what's
1748ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // in the MPEG4 specs and skip it.
1749ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                *offset += chunk_size;
1750ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                return OK;
175172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
175272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1753c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
175472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset = data_offset + sizeof(buffer);
175572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            while (*offset < stop_offset) {
175672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                status_t err = parseChunk(offset, depth + 1);
175772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
175872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
175972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
176072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
1761bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1762bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1763bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1764bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
176572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
176672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
176772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
17685d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('m', 'e', 'a', 'n'):
17695d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('n', 'a', 'm', 'e'):
177072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('d', 'a', 't', 'a'):
177172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
17720517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
17730517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
177472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mPath.size() == 6 && underMetaDataPath(mPath)) {
1775fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                status_t err = parseITunesMetaData(data_offset, chunk_data_size);
177672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
177772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
177872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
177972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
178072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
178172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
178272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
178372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
178472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
178572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'v', 'h', 'd'):
178672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
17870517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
17880517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1789c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (chunk_data_size < 32) {
179072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_MALFORMED;
179172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
179272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1793c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            uint8_t header[32];
179472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
179572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, header, sizeof(header))
179672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    < (ssize_t)sizeof(header)) {
179772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
179872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
179972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1800fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            uint64_t creationTime;
1801c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            uint64_t duration = 0;
180272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (header[0] == 1) {
180372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U64_AT(&header[4]);
1804fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                mHeaderTimescale = U32_AT(&header[20]);
1805c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                duration = U64_AT(&header[24]);
1806c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (duration == 0xffffffffffffffff) {
1807c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    duration = 0;
1808c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1809bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (header[0] != 0) {
1810bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
181172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            } else {
181272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U32_AT(&header[4]);
1813fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                mHeaderTimescale = U32_AT(&header[12]);
1814c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                uint32_t d32 = U32_AT(&header[16]);
1815c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (d32 == 0xffffffff) {
1816c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    d32 = 0;
1817c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1818c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                duration = d32;
1819c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1820e3e82d54c51a3130badcd9e433fe808d965f15c2Joshua J. Drake            if (duration != 0 && mHeaderTimescale != 0) {
1821c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mFileMetaData->setInt64(kKeyDuration, duration * 1000000 / mHeaderTimescale);
182272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
182372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
182472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            String8 s;
182572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            convertTimeToDate(creationTime, &s);
182672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
182772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(kKeyDate, s.string());
182872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
182972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
183072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
183172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1832c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        case FOURCC('m', 'e', 'h', 'd'):
1833c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        {
1834c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            *offset += chunk_size;
1835c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1836c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (chunk_data_size < 8) {
1837c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_MALFORMED;
1838c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1839c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1840c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            uint8_t flags[4];
1841c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (mDataSource->readAt(
1842c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                        data_offset, flags, sizeof(flags))
1843c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    < (ssize_t)sizeof(flags)) {
1844c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_IO;
1845c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1846c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1847c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            uint64_t duration = 0;
1848c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (flags[0] == 1) {
1849c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                // 64 bit
1850c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (chunk_data_size < 12) {
1851c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    return ERROR_MALFORMED;
1852c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1853c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mDataSource->getUInt64(data_offset + 4, &duration);
1854c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (duration == 0xffffffffffffffff) {
1855c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    duration = 0;
1856c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1857c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            } else if (flags[0] == 0) {
1858c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                // 32 bit
1859c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                uint32_t d32;
1860c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mDataSource->getUInt32(data_offset + 4, &d32);
1861c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (d32 == 0xffffffff) {
1862c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    d32 = 0;
1863c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1864c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                duration = d32;
1865c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            } else {
1866c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_MALFORMED;
1867c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1868c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1869e3e82d54c51a3130badcd9e433fe808d965f15c2Joshua J. Drake            if (duration != 0 && mHeaderTimescale != 0) {
1870c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mFileMetaData->setInt64(kKeyDuration, duration * 1000000 / mHeaderTimescale);
1871c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1872c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1873c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            break;
1874c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        }
1875c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1876dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        case FOURCC('m', 'd', 'a', 't'):
1877dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        {
1878ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("mdat chunk, drm: %d", mIsDrm);
1879928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang
1880928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang            mMdatFound = true;
1881928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang
1882dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (!mIsDrm) {
1883dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                *offset += chunk_size;
1884dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                break;
1885dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
1886dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
1887dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (chunk_size < 8) {
1888dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
1889dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
1890dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
1891dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return parseDrmSINF(offset, data_offset);
1892dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
1893dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
18943b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        case FOURCC('h', 'd', 'l', 'r'):
18953b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        {
18960517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
18970517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
18983b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t buffer;
18993b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (mDataSource->readAt(
19003b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                        data_offset + 8, &buffer, 4) < 4) {
19013b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_IO;
19023b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
19033b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
1904f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1905f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1906f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
19073b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type = ntohl(buffer);
19083b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            // For the 3GPP file format, the handler-type within the 'hdlr' box
1909e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            // shall be 'text'. We also want to support 'sbtl' handler type
1910e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            // for a practical reason as various MPEG4 containers use it.
1911e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            if (type == FOURCC('t', 'e', 'x', 't') || type == FOURCC('s', 'b', 't', 'l')) {
19123b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
19133b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
19143b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
19153b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            break;
19163b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        }
19173b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
1918c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        case FOURCC('t', 'r', 'e', 'x'):
1919c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        {
1920c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            *offset += chunk_size;
1921c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1922c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (chunk_data_size < 24) {
1923c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_IO;
1924c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1925c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            Trex trex;
1926c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (!mDataSource->getUInt32(data_offset + 4, &trex.track_ID) ||
1927c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                !mDataSource->getUInt32(data_offset + 8, &trex.default_sample_description_index) ||
1928c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                !mDataSource->getUInt32(data_offset + 12, &trex.default_sample_duration) ||
1929c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                !mDataSource->getUInt32(data_offset + 16, &trex.default_sample_size) ||
1930c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                !mDataSource->getUInt32(data_offset + 20, &trex.default_sample_flags)) {
1931c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_IO;
1932c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1933c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            mTrex.add(trex);
1934c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            break;
1935c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        }
1936c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
19377a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        case FOURCC('t', 'x', '3', 'g'):
19387a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        {
1939f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1940f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1941f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
19423b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type;
19433b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            const void *data;
19443b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            size_t size = 0;
19453b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (!mLastTrack->meta->findData(
19463b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    kKeyTextFormatData, &type, &data, &size)) {
19473b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                size = 0;
19483b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
19493b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
19508da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            uint8_t *buffer = new (std::nothrow) uint8_t[size + chunk_size];
19518da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            if (buffer == NULL) {
19528da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen                return ERROR_MALFORMED;
19538da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            }
19543b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
19553b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (size > 0) {
19563b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                memcpy(buffer, data, size);
19573b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
19583b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
19593b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size))
19603b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    < chunk_size) {
19613b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                delete[] buffer;
19623b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                buffer = NULL;
19633b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
19640517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen                // advance read pointer so we don't end up reading this again
19650517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen                *offset += chunk_size;
19663b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_IO;
19673b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
19683b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
19693b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            mLastTrack->meta->setData(
19703b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    kKeyTextFormatData, 0, buffer, size + chunk_size);
19713b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
19723b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            delete[] buffer;
19737a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
19747a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            *offset += chunk_size;
19757a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            break;
19767a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        }
19777a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
1978515e855eae78aa495da58356486aaa666cb57fd1James Dong        case FOURCC('c', 'o', 'v', 'r'):
1979515e855eae78aa495da58356486aaa666cb57fd1James Dong        {
19800517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
19810517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1982515e855eae78aa495da58356486aaa666cb57fd1James Dong            if (mFileMetaData != NULL) {
19833856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("chunk_data_size = %lld and data_offset = %lld",
1984515e855eae78aa495da58356486aaa666cb57fd1James Dong                        chunk_data_size, data_offset);
19851552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1);
1986515e855eae78aa495da58356486aaa666cb57fd1James Dong                if (mDataSource->readAt(
19871552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                    data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) {
1988515e855eae78aa495da58356486aaa666cb57fd1James Dong                    return ERROR_IO;
1989515e855eae78aa495da58356486aaa666cb57fd1James Dong                }
1990515e855eae78aa495da58356486aaa666cb57fd1James Dong                const int kSkipBytesOfDataBox = 16;
1991515e855eae78aa495da58356486aaa666cb57fd1James Dong                mFileMetaData->setData(
1992515e855eae78aa495da58356486aaa666cb57fd1James Dong                    kKeyAlbumArt, MetaData::TYPE_NONE,
19931552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                    buffer->data() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox);
1994515e855eae78aa495da58356486aaa666cb57fd1James Dong            }
1995515e855eae78aa495da58356486aaa666cb57fd1James Dong
1996515e855eae78aa495da58356486aaa666cb57fd1James Dong            break;
1997515e855eae78aa495da58356486aaa666cb57fd1James Dong        }
1998515e855eae78aa495da58356486aaa666cb57fd1James Dong
1999fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('t', 'i', 't', 'l'):
2000fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('p', 'e', 'r', 'f'):
2001fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'u', 't', 'h'):
2002fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('g', 'n', 'r', 'e'):
2003fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'l', 'b', 'm'):
2004fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('y', 'r', 'r', 'c'):
2005fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
20060517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
20070517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
2008fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            status_t err = parse3GPPMetaData(data_offset, chunk_data_size, depth);
2009fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2010fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (err != OK) {
2011fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                return err;
2012fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2013fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2014fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2015fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2016fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2017328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        case FOURCC('I', 'D', '3', '2'):
2018328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        {
20190517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
20200517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
2021328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            if (chunk_data_size < 6) {
2022328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                return ERROR_MALFORMED;
2023328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            }
2024328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2025328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            parseID3v2MetaData(data_offset + 6);
2026328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2027328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            break;
2028328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        }
2029328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
20305d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('-', '-', '-', '-'):
20315d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        {
20325d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentMean.clear();
20335d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentName.clear();
20345d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentData.clear();
20355d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            *offset += chunk_size;
20365d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            break;
20375d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        }
20385d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen
203905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('s', 'i', 'd', 'x'):
204005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        {
204105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            parseSegmentIndex(data_offset, chunk_data_size);
204205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset += chunk_size;
204305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return UNKNOWN_ERROR; // stop parsing after sidx
204405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
204505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
204620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
204720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
204820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
204920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
205020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
205120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
205220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
205320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
205420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
205520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
205605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) {
205705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen  ALOGV("MPEG4Extractor::parseSegmentIndex");
205805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
205905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 12) {
206005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      return -EINVAL;
206105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
206205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
206305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
206405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) {
206505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
206605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
206705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
206805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t version = flags >> 24;
206905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    flags &= 0xffffff;
207005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
207105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx version %d", version);
207205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
207305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t referenceId;
207405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, &referenceId)) {
207505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
207605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
207705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
207805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t timeScale;
207905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 8, &timeScale)) {
208005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
208105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
208205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx refid/timescale: %d/%d", referenceId, timeScale);
2083e3e82d54c51a3130badcd9e433fe808d965f15c2Joshua J. Drake    if (timeScale == 0)
2084e3e82d54c51a3130badcd9e433fe808d965f15c2Joshua J. Drake        return ERROR_MALFORMED;
208505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
208605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t earliestPresentationTime;
208705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t firstOffset;
208805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
208905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 12;
209005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 12;
209105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
209205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (version == 0) {
209305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 8) {
209405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
209505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
209605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t tmp;
209705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
209805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
209905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
210005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        earliestPresentationTime = tmp;
210105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset + 4, &tmp)) {
210205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
210305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
210405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        firstOffset = tmp;
210505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 8;
210605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 8;
210705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
210805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 16) {
210905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
211005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
211105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset, &earliestPresentationTime)) {
211205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
211305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
211405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset + 8, &firstOffset)) {
211505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
211605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
211705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 16;
211805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 16;
211905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
2120a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("sidx pres/off: %" PRIu64 "/%" PRIu64, earliestPresentationTime, firstOffset);
212105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
212205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 4) {
212305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
212405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
212505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
212605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint16_t referenceCount;
212705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt16(offset + 2, &referenceCount)) {
212805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
212905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
213005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 4;
213105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 4;
213205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("refcount: %d", referenceCount);
213305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
213405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < referenceCount * 12) {
213505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
213605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
213705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
213805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t total_duration = 0;
213905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    for (unsigned int i = 0; i < referenceCount; i++) {
214005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t d1, d2, d3;
214105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
214205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &d1) ||     // size
214305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            !mDataSource->getUInt32(offset + 4, &d2) || // duration
214405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            !mDataSource->getUInt32(offset + 8, &d3)) { // flags
214505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
214605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
214705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
214805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (d1 & 0x80000000) {
214905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGW("sub-sidx boxes not supported yet");
215005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
215105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool sap = d3 & 0x80000000;
21523f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen        uint32_t saptype = (d3 >> 28) & 7;
21533f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen        if (!sap || (saptype != 1 && saptype != 2)) {
21543f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            // type 1 and 2 are sync samples
21553f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            ALOGW("not a stream access point, or unsupported type: %08x", d3);
215605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
215705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        total_duration += d2;
215805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 12;
215905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV(" item %d, %08x %08x %08x", i, d1, d2, d3);
216005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        SidxEntry se;
216105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        se.mSize = d1 & 0x7fffffff;
216205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        se.mDurationUs = 1000000LL * d2 / timeScale;
216305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mSidxEntries.add(se);
216405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
216505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2166c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    uint64_t sidxDuration = total_duration * 1000000 / timeScale;
216705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2168f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake    if (mLastTrack == NULL)
2169f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake        return ERROR_MALFORMED;
2170f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
217105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t metaDuration;
217205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mLastTrack->meta->findInt64(kKeyDuration, &metaDuration) || metaDuration == 0) {
2173c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        mLastTrack->meta->setInt64(kKeyDuration, sidxDuration);
217405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
217505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
217605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
217705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
217805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
217905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2180ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huberstatus_t MPEG4Extractor::parseTrackHeader(
2181c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t data_offset, off64_t data_size) {
2182ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (data_size < 4) {
2183ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_MALFORMED;
2184ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2185ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2186ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint8_t version;
2187ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (mDataSource->readAt(data_offset, &version, 1) < 1) {
2188ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_IO;
2189ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2190ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2191ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    size_t dynSize = (version == 1) ? 36 : 24;
2192ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2193ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint8_t buffer[36 + 60];
2194ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2195c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    if (data_size != (off64_t)dynSize + 60) {
2196ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_MALFORMED;
2197ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2198ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2199ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (mDataSource->readAt(
2200ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber                data_offset, buffer, data_size) < (ssize_t)data_size) {
2201ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_IO;
2202ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2203ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2204b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    uint64_t ctime __unused, mtime __unused, duration __unused;
2205ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t id;
2206ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2207ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (version == 1) {
2208ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        ctime = U64_AT(&buffer[4]);
2209ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mtime = U64_AT(&buffer[12]);
2210ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        id = U32_AT(&buffer[20]);
2211ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        duration = U64_AT(&buffer[28]);
221204022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen    } else if (version == 0) {
2213ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        ctime = U32_AT(&buffer[4]);
2214ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mtime = U32_AT(&buffer[8]);
2215ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        id = U32_AT(&buffer[12]);
2216ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        duration = U32_AT(&buffer[20]);
221704022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen    } else {
221804022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen        return ERROR_UNSUPPORTED;
2219ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2220ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2221f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake    if (mLastTrack == NULL)
2222f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake        return ERROR_MALFORMED;
2223f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
2224ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    mLastTrack->meta->setInt32(kKeyTrackID, id);
2225ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2226ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    size_t matrixOffset = dynSize + 16;
2227ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a00 = U32_AT(&buffer[matrixOffset]);
2228ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a01 = U32_AT(&buffer[matrixOffset + 4]);
2229ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a10 = U32_AT(&buffer[matrixOffset + 12]);
2230ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a11 = U32_AT(&buffer[matrixOffset + 16]);
2231ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2232ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#if 0
2233b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    int32_t dx = U32_AT(&buffer[matrixOffset + 8]);
2234b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    int32_t dy = U32_AT(&buffer[matrixOffset + 20]);
2235b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe
2236df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("x' = %.2f * x + %.2f * y + %.2f",
2237ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber         a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f);
2238df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("y' = %.2f * x + %.2f * y + %.2f",
2239ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber         a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f);
2240ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#endif
2241ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2242ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t rotationDegrees;
2243ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2244ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    static const int32_t kFixedOne = 0x10000;
2245ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) {
2246ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        // Identity, no rotation
2247ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 0;
2248ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) {
2249ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 90;
2250ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) {
2251ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 270;
2252ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) {
2253ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 180;
2254ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else {
22555ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("We only support 0,90,180,270 degree rotation matrices");
2256ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 0;
2257ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2258ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2259ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (rotationDegrees != 0) {
2260ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees);
2261ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2262ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2263b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    // Handle presentation display size, which could be different
2264b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    // from the image size indicated by kKeyWidth and kKeyHeight.
2265ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t width = U32_AT(&buffer[dynSize + 52]);
2266ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t height = U32_AT(&buffer[dynSize + 56]);
2267b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    mLastTrack->meta->setInt32(kKeyDisplayWidth, width >> 16);
2268b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    mLastTrack->meta->setInt32(kKeyDisplayHeight, height >> 16);
2269ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2270ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    return OK;
2271ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber}
2272ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2273fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhéstatus_t MPEG4Extractor::parseITunesMetaData(off64_t offset, size_t size) {
227472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (size < 4) {
227572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_MALFORMED;
227672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
227772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
22788da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    uint8_t *buffer = new (std::nothrow) uint8_t[size + 1];
22798da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    if (buffer == NULL) {
22808da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        return ERROR_MALFORMED;
22818da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    }
228272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (mDataSource->readAt(
228372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                offset, buffer, size) != (ssize_t)size) {
228472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        delete[] buffer;
228572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        buffer = NULL;
228672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
228772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_IO;
228872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
228972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
229072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t flags = U32_AT(buffer);
229172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
229272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t metadataKey = 0;
22935d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    char chunk[5];
22945d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    MakeFourCCString(mPath[4], chunk);
22955d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    ALOGV("meta: %s @ %lld", chunk, offset);
22962d0ac425564ff9882ebaac5267d1a04d4af67d00Bernhard Rosenkränzer    switch ((int32_t)mPath[4]) {
229772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'a', 'l', 'b'):
229872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
229972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbum;
230072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
230172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
230272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'A', 'R', 'T'):
230372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
230472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyArtist;
230572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
230672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
230766ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        case FOURCC('a', 'A', 'R', 'T'):
230866ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        {
230966ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            metadataKey = kKeyAlbumArtist;
231066ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            break;
231166ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        }
231272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'd', 'a', 'y'):
231372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
231472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyYear;
231572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
231672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
231772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'n', 'a', 'm'):
231872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
231972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyTitle;
232072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
232172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
232272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'w', 'r', 't'):
232372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
232472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyWriter;
232572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
232672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
232772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('c', 'o', 'v', 'r'):
232872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
232972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbumArt;
233072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
233172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
233272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('g', 'n', 'r', 'e'):
233372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
233472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyGenre;
233572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
233672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
233726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC(0xa9, 'g', 'e', 'n'):
233826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
233926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            metadataKey = kKeyGenre;
234026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
234126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
234211f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        case FOURCC('c', 'p', 'i', 'l'):
234311f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        {
234411f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            if (size == 9 && flags == 21) {
234511f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                char tmp[16];
234611f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                sprintf(tmp, "%d",
234711f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                        (int)buffer[size - 1]);
234811f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen
234911f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                mFileMetaData->setCString(kKeyCompilation, tmp);
235011f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            }
235111f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            break;
235211f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        }
235372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('t', 'r', 'k', 'n'):
235472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
235572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (size == 16 && flags == 0) {
235672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char tmp[16];
2357afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTrack = (uint16_t*)&buffer[10];
2358afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTotalTracks = (uint16_t*)&buffer[12];
2359afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                sprintf(tmp, "%d/%d", ntohs(*pTrack), ntohs(*pTotalTracks));
236072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
236172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
236272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
236372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
236472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
236526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC('d', 'i', 's', 'k'):
236626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
2367afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik            if ((size == 14 || size == 16) && flags == 0) {
236826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                char tmp[16];
2369afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pDisc = (uint16_t*)&buffer[10];
2370afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTotalDiscs = (uint16_t*)&buffer[12];
2371afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                sprintf(tmp, "%d/%d", ntohs(*pDisc), ntohs(*pTotalDiscs));
237226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
237326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(kKeyDiscNumber, tmp);
237426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            }
237526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
237626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
23775d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('-', '-', '-', '-'):
23785d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        {
23795d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            buffer[size] = '\0';
23805d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            switch (mPath[5]) {
23815d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('m', 'e', 'a', 'n'):
23825d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentMean.setTo((const char *)buffer + 4);
23835d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
23845d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('n', 'a', 'm', 'e'):
23855d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentName.setTo((const char *)buffer + 4);
23865d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
23875d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('d', 'a', 't', 'a'):
23885d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentData.setTo((const char *)buffer + 8);
23895d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
23905d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            }
23918c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
23928c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // Once we have a set of mean/name/data info, go ahead and process
23938c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // it to see if its something we are interested in.  Whether or not
23948c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // were are interested in the specific tag, make sure to clear out
23958c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // the set so we can be ready to process another tuple should one
23968c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // show up later in the file.
23978c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            if ((mLastCommentMean.length() != 0) &&
23988c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                (mLastCommentName.length() != 0) &&
23998c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                (mLastCommentData.length() != 0)) {
24008c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
24018c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                if (mLastCommentMean == "com.apple.iTunes"
24028c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        && mLastCommentName == "iTunSMPB") {
24038c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    int32_t delay, padding;
24048c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    if (sscanf(mLastCommentData,
24058c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                               " %*x %x %x %*x", &delay, &padding) == 2) {
2406f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                        if (mLastTrack == NULL)
2407f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                            return ERROR_MALFORMED;
2408f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
24098c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
24108c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        mLastTrack->meta->setInt32(kKeyEncoderPadding, padding);
24118c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    }
24125d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                }
24138c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
24145d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentMean.clear();
24155d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentName.clear();
24165d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentData.clear();
24175d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            }
24185d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            break;
24195d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        }
242026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
242172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        default:
242272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
242372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
242472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
2425328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    if (size >= 8 && metadataKey && !mFileMetaData->hasData(metadataKey)) {
242672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        if (metadataKey == kKeyAlbumArt) {
242772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setData(
242872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    kKeyAlbumArt, MetaData::TYPE_NONE,
242972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    buffer + 8, size - 8);
243072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else if (metadataKey == kKeyGenre) {
243172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (flags == 0) {
243226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // uint8_t genre code, iTunes genre codes are
243326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // the standard id3 codes, except they start
243426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // at 1 instead of 0 (e.g. Pop is 14, not 13)
243526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // We use standard id3 numbering, so subtract 1.
243626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                int genrecode = (int)buffer[size - 1];
243726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                genrecode--;
243826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                if (genrecode < 0) {
243926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                    genrecode = 255; // reserved for 'unknown genre'
244026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                }
244172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char genre[10];
244226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                sprintf(genre, "%d", genrecode);
244372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
244472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(metadataKey, genre);
244526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            } else if (flags == 1) {
244626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // custom genre string
244726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                buffer[size] = '\0';
244826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
244926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(
245026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                        metadataKey, (const char *)buffer + 8);
245172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
245272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else {
245372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            buffer[size] = '\0';
245472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
245572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(
245672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    metadataKey, (const char *)buffer + 8);
245772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
245872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
245972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
246072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    delete[] buffer;
246172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    buffer = NULL;
246272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
246372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return OK;
246472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
246572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
2466fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhéstatus_t MPEG4Extractor::parse3GPPMetaData(off64_t offset, size_t size, int depth) {
2467fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    if (size < 4) {
2468fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        return ERROR_MALFORMED;
2469fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2470fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
24718da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    uint8_t *buffer = new (std::nothrow) uint8_t[size];
24728da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    if (buffer == NULL) {
24738da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        return ERROR_MALFORMED;
24748da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    }
2475fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    if (mDataSource->readAt(
2476fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                offset, buffer, size) != (ssize_t)size) {
2477fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        delete[] buffer;
2478fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        buffer = NULL;
2479fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2480fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        return ERROR_IO;
2481fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2482fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2483fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    uint32_t metadataKey = 0;
2484fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    switch (mPath[depth]) {
2485fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('t', 'i', 't', 'l'):
2486fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2487fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyTitle;
2488fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2489fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2490fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('p', 'e', 'r', 'f'):
2491fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2492fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyArtist;
2493fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2494fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2495fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'u', 't', 'h'):
2496fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2497fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyWriter;
2498fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2499fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2500fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('g', 'n', 'r', 'e'):
2501fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2502fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyGenre;
2503fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2504fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2505fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'l', 'b', 'm'):
2506fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2507fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (buffer[size - 1] != '\0') {
2508fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé              char tmp[4];
2509fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé              sprintf(tmp, "%u", buffer[size - 1]);
2510fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2511fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé              mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
2512fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2513fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2514fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyAlbum;
2515fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2516fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2517fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('y', 'r', 'r', 'c'):
2518fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2519fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            char tmp[5];
2520fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            uint16_t year = U16_AT(&buffer[4]);
2521fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2522fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (year < 10000) {
2523fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                sprintf(tmp, "%u", year);
2524fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2525fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                mFileMetaData->setCString(kKeyYear, tmp);
2526fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2527fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2528fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2529fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2530fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        default:
2531fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2532fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2533fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2534fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    if (metadataKey > 0) {
2535fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        bool isUTF8 = true; // Common case
2536fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        char16_t *framedata = NULL;
2537fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        int len16 = 0; // Number of UTF-16 characters
2538fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2539fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        // smallest possible valid UTF-16 string w BOM: 0xfe 0xff 0x00 0x00
2540fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        if (size - 6 >= 4) {
2541fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            len16 = ((size - 6) / 2) - 1; // don't include 0x0000 terminator
2542fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            framedata = (char16_t *)(buffer + 6);
2543fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (0xfffe == *framedata) {
2544fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                // endianness marker (BOM) doesn't match host endianness
2545fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                for (int i = 0; i < len16; i++) {
2546fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                    framedata[i] = bswap_16(framedata[i]);
2547fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                }
2548fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                // BOM is now swapped to 0xfeff, we will execute next block too
2549fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2550fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2551fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (0xfeff == *framedata) {
2552fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                // Remove the BOM
2553fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                framedata++;
2554fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                len16--;
2555fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                isUTF8 = false;
2556fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2557fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // else normal non-zero-length UTF-8 string
2558fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // we can't handle UTF-16 without BOM as there is no other
2559fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // indication of encoding.
2560fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2561fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2562fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        if (isUTF8) {
2563fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            mFileMetaData->setCString(metadataKey, (const char *)buffer + 6);
2564fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        } else {
2565fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // Convert from UTF-16 string to UTF-8 string.
2566fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            String8 tmpUTF8str(framedata, len16);
2567fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            mFileMetaData->setCString(metadataKey, tmpUTF8str.string());
2568fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2569fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2570fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2571fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    delete[] buffer;
2572fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    buffer = NULL;
2573fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2574fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    return OK;
2575fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé}
2576fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2577328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhévoid MPEG4Extractor::parseID3v2MetaData(off64_t offset) {
2578328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    ID3 id3(mDataSource, true /* ignorev1 */, offset);
2579328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2580328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    if (id3.isValid()) {
2581328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        struct Map {
2582328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            int key;
2583328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            const char *tag1;
2584328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            const char *tag2;
2585328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        };
2586328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        static const Map kMap[] = {
2587328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyAlbum, "TALB", "TAL" },
2588328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyArtist, "TPE1", "TP1" },
2589328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyAlbumArtist, "TPE2", "TP2" },
2590328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyComposer, "TCOM", "TCM" },
2591328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyGenre, "TCON", "TCO" },
2592328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyTitle, "TIT2", "TT2" },
2593328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyYear, "TYE", "TYER" },
2594328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyAuthor, "TXT", "TEXT" },
2595328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyCDTrackNumber, "TRK", "TRCK" },
2596328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyDiscNumber, "TPA", "TPOS" },
2597328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyCompilation, "TCP", "TCMP" },
2598328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        };
2599328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
2600328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2601328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        for (size_t i = 0; i < kNumMapEntries; ++i) {
2602328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            if (!mFileMetaData->hasData(kMap[i].key)) {
2603328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                ID3::Iterator *it = new ID3::Iterator(id3, kMap[i].tag1);
2604328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                if (it->done()) {
2605328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    delete it;
2606328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    it = new ID3::Iterator(id3, kMap[i].tag2);
2607328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                }
2608328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2609328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                if (it->done()) {
2610328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    delete it;
2611328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    continue;
2612328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                }
2613328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2614328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                String8 s;
2615328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                it->getString(&s);
2616328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                delete it;
2617328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2618328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                mFileMetaData->setCString(kMap[i].key, s);
2619328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            }
2620328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        }
2621328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2622328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        size_t dataSize;
2623328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        String8 mime;
2624328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        const void *data = id3.getAlbumArt(&dataSize, &mime);
2625328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2626328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        if (data) {
2627328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            mFileMetaData->setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize);
2628328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            mFileMetaData->setCString(kKeyAlbumArtMIME, mime.string());
2629328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        }
2630328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    }
2631328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé}
2632328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2633693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
263420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
263520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
2636693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return NULL;
263720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
263820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
263920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
264020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
264120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
2642693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber            return NULL;
264320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
264420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
264520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
264620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
264720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
264820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2649371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
2650371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
2651371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
2652371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
2653c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
2654c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    Trex *trex = NULL;
2655c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    int32_t trackId;
2656c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    if (track->meta->findInt32(kKeyTrackID, &trackId)) {
2657c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        for (size_t i = 0; i < mTrex.size(); i++) {
2658c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            Trex *t = &mTrex.editItemAt(index);
2659c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (t->track_ID == (uint32_t) trackId) {
2660c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                trex = t;
2661c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                break;
2662c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
2663c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        }
2664c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    }
2665c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
2666a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("getTrack called, pssh: %zu", mPssh.size());
2667ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2668942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    return new MPEG4Source(this,
266905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            track->meta, mDataSource, track->timescale, track->sampleTable,
2670c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            mSidxEntries, trex, mMoofOffset);
267120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
267220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2673bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber// static
2674bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) {
2675bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const char *mime;
2676bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    CHECK(track->meta->findCString(kKeyMIMEType, &mime));
2677bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2678bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    uint32_t type;
2679bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const void *data;
2680bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    size_t size;
2681bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
2682bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyAVCC, &type, &data, &size)
2683bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeAVCC) {
2684bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
2685bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
26863b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
26873b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        if (!track->meta->findData(kKeyHVCC, &type, &data, &size)
26883b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar                    || type != kTypeHVCC) {
26893b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            return ERROR_MALFORMED;
26903b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        }
2691bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
2692bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
2693bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyESDS, &type, &data, &size)
2694bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeESDS) {
2695bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
2696bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
2697bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    }
2698bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2699ce171998009e1abcb0c718c0aee495fcd33645e2Robert Shih    if (track->sampleTable == NULL || !track->sampleTable->isValid()) {
2700169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        // Make sure we have all the metadata we need.
2701ce171998009e1abcb0c718c0aee495fcd33645e2Robert Shih        ALOGE("stbl atom missing/invalid.");
2702169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        return ERROR_MALFORMED;
2703169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber    }
2704169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber
2705bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    return OK;
2706bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber}
2707bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2708f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivitypedef enum {
2709f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_NONE             = -1,
2710f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_NULL_OBJECT      = 0,
2711f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_MAIN         = 1, /**< Main profile                              */
2712f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_AAC_LC           = 2,   /**< Low Complexity object                     */
2713f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_SSR          = 3,
2714f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_LTP          = 4,
2715f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_SBR              = 5,
2716f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_SCAL         = 6,
2717f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_TWIN_VQ          = 7,
2718f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_CELP             = 8,
2719f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_HVXC             = 9,
2720f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_10          = 10, /**< (reserved)                                */
2721f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_11          = 11, /**< (reserved)                                */
2722f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_TTSI             = 12, /**< TTSI Object                               */
2723f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MAIN_SYNTH       = 13, /**< Main Synthetic object                     */
2724f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_WAV_TAB_SYNTH    = 14, /**< Wavetable Synthesis object                */
2725f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_GEN_MIDI         = 15, /**< General MIDI object                       */
2726f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ALG_SYNTH_AUD_FX = 16, /**< Algorithmic Synthesis and Audio FX object */
2727f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_AAC_LC        = 17,   /**< Error Resilient(ER) AAC Low Complexity    */
2728f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_18          = 18, /**< (reserved)                                */
2729f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_AAC_LTP       = 19, /**< Error Resilient(ER) AAC LTP object        */
2730f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_AAC_SCAL      = 20,   /**< Error Resilient(ER) AAC Scalable object   */
2731f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_TWIN_VQ       = 21, /**< Error Resilient(ER) TwinVQ object         */
2732f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_BSAC          = 22,   /**< Error Resilient(ER) BSAC object           */
2733f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_AAC_LD        = 23,   /**< Error Resilient(ER) AAC LowDelay object   */
2734f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_CELP          = 24, /**< Error Resilient(ER) CELP object           */
2735f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_HVXC          = 25, /**< Error Resilient(ER) HVXC object           */
2736f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_HILN          = 26, /**< Error Resilient(ER) HILN object           */
2737f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_PARA          = 27, /**< Error Resilient(ER) Parametric object     */
2738f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_28          = 28, /**< might become SSC                          */
2739f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_PS               = 29,   /**< PS, Parametric Stereo (includes SBR)      */
2740f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MPEGS            = 30, /**< MPEG Surround                             */
2741f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2742f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ESCAPE           = 31,   /**< Signal AOT uses more than 5 bits          */
2743f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2744f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MP3ONMP4_L1      = 32, /**< MPEG-Layer1 in mp4                        */
2745f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MP3ONMP4_L2      = 33, /**< MPEG-Layer2 in mp4                        */
2746f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MP3ONMP4_L3      = 34, /**< MPEG-Layer3 in mp4                        */
2747f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_35          = 35, /**< might become DST                          */
2748f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_36          = 36, /**< might become ALS                          */
2749f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_SLS          = 37, /**< AAC + SLS                                 */
2750f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_SLS              = 38, /**< SLS                                       */
2751f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_AAC_ELD       = 39, /**< AAC Enhanced Low Delay                    */
2752f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2753f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_USAC             = 42, /**< USAC                                      */
2754f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_SAOC             = 43, /**< SAOC                                      */
2755f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_LD_MPEGS         = 44, /**< Low Delay MPEG Surround                   */
2756f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2757f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD50           = 50,  /**< Interim AOT for Rsvd50                   */
2758f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi} AUDIO_OBJECT_TYPE;
2759f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2760ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
2761ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        const void *esds_data, size_t esds_size) {
2762ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    ESDS esds(esds_data, esds_size);
276381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
276481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    uint8_t objectTypeIndication;
276581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
276681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return ERROR_MALFORMED;
276781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
276881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
276981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (objectTypeIndication == 0xe1) {
277081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        // This isn't MPEG4 audio at all, it's QCELP 14k...
2771f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake        if (mLastTrack == NULL)
2772f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            return ERROR_MALFORMED;
2773f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
277481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
277581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return OK;
277681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
277781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
2778633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong    if (objectTypeIndication  == 0x6b) {
2779633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // The media subtype is MP3 audio
2780633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // Our software MP3 audio decoder may not be able to handle
2781633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // packetized MP3 audio; for now, lets just return ERROR_UNSUPPORTED
278229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("MP3 track in MP4/3GPP file is not supported");
2783633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        return ERROR_UNSUPPORTED;
2784633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong    }
2785633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong
2786ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    const uint8_t *csd;
2787ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    size_t csd_size;
2788ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (esds.getCodecSpecificInfo(
2789ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                (const void **)&csd, &csd_size) != OK) {
2790ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
2791ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2792ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2793b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    if (kUseHexDump) {
2794b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        printf("ESD of size %d\n", csd_size);
2795b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        hexdump(csd, csd_size);
2796b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    }
2797ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2798a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    if (csd_size == 0) {
2799a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // There's no further information, i.e. no codec specific data
2800a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // Let's assume that the information provided in the mpeg4 headers
2801a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // is accurate and hope for the best.
2802a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
2803a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        return OK;
2804a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    }
2805a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
2806ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (csd_size < 2) {
2807ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
2808ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2809ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
281000307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent    static uint32_t kSamplingRate[] = {
281100307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
281200307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        16000, 12000, 11025, 8000, 7350
281300307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent    };
281400307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent
2815aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    ABitReader br(csd, csd_size);
2816aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    uint32_t objectType = br.getBits(5);
2817ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2818aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    if (objectType == 31) {  // AAC-ELD => additional 6 bits
2819aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        objectType = 32 + br.getBits(6);
2820ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2821ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2822f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake    if (mLastTrack == NULL)
2823f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake        return ERROR_MALFORMED;
2824f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
2825db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent    //keep AOT type
2826db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent    mLastTrack->meta->setInt32(kKeyAACAOT, objectType);
2827db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent
2828aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    uint32_t freqIndex = br.getBits(4);
2829aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
2830ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t sampleRate = 0;
2831ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t numChannels = 0;
2832ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (freqIndex == 15) {
2833ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        if (csd_size < 5) {
2834ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            return ERROR_MALFORMED;
2835ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
2836aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        sampleRate = br.getBits(24);
2837aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        numChannels = br.getBits(4);
2838ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    } else {
2839595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen        numChannels = br.getBits(4);
284000307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent
284100307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        if (freqIndex == 13 || freqIndex == 14) {
284200307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            return ERROR_MALFORMED;
2843ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
2844ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
284500307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        sampleRate = kSamplingRate[freqIndex];
284600307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent    }
2847595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen
2848f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    if (objectType == AOT_SBR || objectType == AOT_PS) {//SBR specific config per 14496-3 table 1.13
284900307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        uint32_t extFreqIndex = br.getBits(4);
2850b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        int32_t extSampleRate __unused;
285100307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        if (extFreqIndex == 15) {
285200307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            if (csd_size < 8) {
2853595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen                return ERROR_MALFORMED;
2854595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen            }
285500307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            extSampleRate = br.getBits(24);
285600307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        } else {
285700307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            if (extFreqIndex == 13 || extFreqIndex == 14) {
285800307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent                return ERROR_MALFORMED;
285900307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            }
286000307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            extSampleRate = kSamplingRate[extFreqIndex];
2861595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen        }
286200307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        //TODO: save the extension sampling rate value in meta data =>
286300307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        //      mLastTrack->meta->setInt32(kKeyExtSampleRate, extSampleRate);
2864ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2865ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2866f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    switch (numChannels) {
2867f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        // values defined in 14496-3_2009 amendment-4 Table 1.19 - Channel Configuration
2868f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 0:
2869f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 1:// FC
2870f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 2:// FL FR
2871f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 3:// FC, FL FR
2872f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 4:// FC, FL FR, RC
2873f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 5:// FC, FL FR, SL SR
2874f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 6:// FC, FL FR, SL SR, LFE
2875f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            //numChannels already contains the right value
2876f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            break;
2877f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 11:// FC, FL FR, SL SR, RC, LFE
2878f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            numChannels = 7;
2879f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            break;
2880f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 7: // FC, FCL FCR, FL FR, SL SR, LFE
2881f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 12:// FC, FL  FR,  SL SR, RL RR, LFE
2882f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 14:// FC, FL  FR,  SL SR, LFE, FHL FHR
2883f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            numChannels = 8;
2884f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            break;
2885f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        default:
2886f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            return ERROR_UNSUPPORTED;
2887f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    }
2888f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2889f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    {
2890f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        if (objectType == AOT_SBR || objectType == AOT_PS) {
2891f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            objectType = br.getBits(5);
2892f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2893f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            if (objectType == AOT_ESCAPE) {
2894f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                objectType = 32 + br.getBits(6);
2895f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            }
2896f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        }
2897f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        if (objectType == AOT_AAC_LC || objectType == AOT_ER_AAC_LC ||
2898f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                objectType == AOT_ER_AAC_LD || objectType == AOT_ER_AAC_SCAL ||
2899f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                objectType == AOT_ER_BSAC) {
2900b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe            const int32_t frameLengthFlag __unused = br.getBits(1);
2901f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2902f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            const int32_t dependsOnCoreCoder = br.getBits(1);
2903f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2904f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            if (dependsOnCoreCoder ) {
2905b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                const int32_t coreCoderDelay __unused = br.getBits(14);
2906f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            }
2907f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
290845452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            int32_t extensionFlag = -1;
290945452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            if (br.numBitsLeft() > 0) {
291045452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                extensionFlag = br.getBits(1);
291145452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            } else {
291245452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                switch (objectType) {
291345452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                // 14496-3 4.5.1.1 extensionFlag
291445452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_AAC_LC:
291545452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    extensionFlag = 0;
291645452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    break;
291745452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_ER_AAC_LC:
291845452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_ER_AAC_SCAL:
291945452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_ER_BSAC:
292045452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_ER_AAC_LD:
292145452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    extensionFlag = 1;
292245452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    break;
292345452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                default:
292445452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    TRESPASS();
292545452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    break;
292645452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                }
292745452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                ALOGW("csd missing extension flag; assuming %d for object type %u.",
292845452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                        extensionFlag, objectType);
292945452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            }
2930f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
293145452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            if (numChannels == 0) {
2932f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                int32_t channelsEffectiveNum = 0;
2933f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                int32_t channelsNum = 0;
2934b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                const int32_t ElementInstanceTag __unused = br.getBits(4);
2935b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                const int32_t Profile __unused = br.getBits(2);
2936b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                const int32_t SamplingFrequencyIndex __unused = br.getBits(4);
2937f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumFrontChannelElements = br.getBits(4);
2938f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumSideChannelElements = br.getBits(4);
2939f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumBackChannelElements = br.getBits(4);
2940f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumLfeChannelElements = br.getBits(2);
2941b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                const int32_t NumAssocDataElements __unused = br.getBits(3);
2942b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                const int32_t NumValidCcElements __unused = br.getBits(4);
2943f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2944f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t MonoMixdownPresent = br.getBits(1);
2945f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                if (MonoMixdownPresent != 0) {
2946b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t MonoMixdownElementNumber __unused = br.getBits(4);
2947f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2948f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2949f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t StereoMixdownPresent = br.getBits(1);
2950f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                if (StereoMixdownPresent != 0) {
2951b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t StereoMixdownElementNumber __unused = br.getBits(4);
2952f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2953f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2954f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t MatrixMixdownIndexPresent = br.getBits(1);
2955f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                if (MatrixMixdownIndexPresent != 0) {
2956b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t MatrixMixdownIndex __unused = br.getBits(2);
2957b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t PseudoSurroundEnable __unused = br.getBits(1);
2958f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2959f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2960f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                int i;
2961f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumFrontChannelElements; i++) {
2962f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t FrontElementIsCpe = br.getBits(1);
2963b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t FrontElementTagSelect __unused = br.getBits(4);
2964f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += FrontElementIsCpe ? 2 : 1;
2965f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2966f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2967f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumSideChannelElements; i++) {
2968f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t SideElementIsCpe = br.getBits(1);
2969b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t SideElementTagSelect __unused = br.getBits(4);
2970f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += SideElementIsCpe ? 2 : 1;
2971f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2972f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2973f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumBackChannelElements; i++) {
2974f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t BackElementIsCpe = br.getBits(1);
2975b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t BackElementTagSelect __unused = br.getBits(4);
2976f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += BackElementIsCpe ? 2 : 1;
2977f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2978f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                channelsEffectiveNum = channelsNum;
2979f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2980f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumLfeChannelElements; i++) {
2981b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t LfeElementTagSelect __unused = br.getBits(4);
2982f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += 1;
2983f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2984f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                ALOGV("mpeg4 audio channelsNum = %d", channelsNum);
2985f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                ALOGV("mpeg4 audio channelsEffectiveNum = %d", channelsEffectiveNum);
2986f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                numChannels = channelsNum;
2987f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            }
2988f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        }
2989f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    }
2990f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2991ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (numChannels == 0) {
2992ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_UNSUPPORTED;
2993ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2994ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2995f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake    if (mLastTrack == NULL)
2996f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake        return ERROR_MALFORMED;
2997f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
2998ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevSampleRate;
2999ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
3000ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3001ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevSampleRate != sampleRate) {
30023856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("mpeg4 audio sample rate different from previous setting. "
3003ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevSampleRate, sampleRate);
3004ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
3005ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3006ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
3007ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3008ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevChannelCount;
3009ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
3010ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3011ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevChannelCount != numChannels) {
30123856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("mpeg4 audio channel count different from previous setting. "
3013ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevChannelCount, numChannels);
3014ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
3015ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3016ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
3017ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3018ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    return OK;
3019ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber}
3020ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
302120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
302220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
302320111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::MPEG4Source(
3024942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen        const sp<MPEG4Extractor> &owner,
302520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        const sp<MetaData> &format,
3026693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &dataSource,
302748c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        int32_t timeScale,
302805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const sp<SampleTable> &sampleTable,
302905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        Vector<SidxEntry> &sidx,
3030c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        const Trex *trex,
303105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t firstMoofOffset)
3032942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    : mOwner(owner),
3033942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen      mFormat(format),
303420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDataSource(dataSource),
303548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber      mTimescale(timeScale),
303620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSampleTable(sampleTable),
303720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCurrentSampleIndex(0),
303805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentFragmentIndex(0),
303905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mSegments(sidx),
3040c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen      mTrex(trex),
304105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mFirstMoofOffset(firstMoofOffset),
304205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentMoofOffset(firstMoofOffset),
304305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentTime(0),
3044ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoAllocSize(0),
3045ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoSizes(NULL),
3046ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoOffsetsAllocSize(0),
3047ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoOffsets(NULL),
304820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mIsAVC(false),
30493b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar      mIsHEVC(false),
30506064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber      mNALLengthSize(0),
305120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mStarted(false),
305220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mGroup(NULL),
305320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mBuffer(NULL),
3054dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber      mWantsNALFragments(false),
30550024245e134467d120b40099da16c467dc365e76Andreas Huber      mSrcBuffer(NULL) {
3056ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3057c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    memset(&mTrackFragmentHeaderInfo, 0, sizeof(mTrackFragmentHeaderInfo));
3058c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
3059ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mFormat->findInt32(kKeyCryptoMode, &mCryptoMode);
306048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    mDefaultIVSize = 0;
3061ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mFormat->findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize);
3062ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t keytype;
3063ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    const void *key;
3064ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    size_t keysize;
3065ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mFormat->findData(kKeyCryptoKey, &keytype, &key, &keysize)) {
3066ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        CHECK(keysize <= 16);
3067ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memset(mCryptoKey, 0, 16);
3068ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memcpy(mCryptoKey, key, keysize);
3069ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3070ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
307120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
307220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mFormat->findCString(kKeyMIMEType, &mime);
3073dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(success);
307420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
307518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber    mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
30763b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    mIsHEVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC);
30776064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
30786064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    if (mIsAVC) {
30796064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        uint32_t type;
30806064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const void *data;
30816064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t size;
30826064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(format->findData(kKeyAVCC, &type, &data, &size));
30836064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
30846064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const uint8_t *ptr = (const uint8_t *)data;
30856064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
30866064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(size >= 7);
3087ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
30886064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
30896064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        // The number of bytes used to encode the length of a NAL unit.
30906064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        mNALLengthSize = 1 + (ptr[4] & 3);
30913b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    } else if (mIsHEVC) {
30923b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        uint32_t type;
30933b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        const void *data;
30943b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        size_t size;
30953b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        CHECK(format->findData(kKeyHVCC, &type, &data, &size));
30963b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
30973b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        const uint8_t *ptr = (const uint8_t *)data;
30983b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
30993b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        CHECK(size >= 7);
31003b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
31013b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
31023b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        mNALLengthSize = 1 + (ptr[14 + 7] & 3);
31036064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
310405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
310505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    CHECK(format->findInt32(kKeyTrackID, &mTrackId));
310605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
310705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mFirstMoofOffset != 0) {
310805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t offset = mFirstMoofOffset;
310905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        parseChunk(&offset);
311005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
311120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
311220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
311320111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::~MPEG4Source() {
311420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mStarted) {
311520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        stop();
311620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
3117ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    free(mCurrentSampleInfoSizes);
3118ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    free(mCurrentSampleInfoOffsets);
311920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
312020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
312120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::start(MetaData *params) {
31227b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
31237b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
3124dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(!mStarted);
312520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
312620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t val;
3127dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (params && params->findInt32(kKeyWantsNALFragments, &val)
312820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        && val != 0) {
3129dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = true;
313020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    } else {
3131dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = false;
313220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
313320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
313420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = new MediaBufferGroup;
313520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3136738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    int32_t max_size;
3137738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
313820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3139738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    mGroup->add_buffer(new MediaBuffer(max_size));
31400024245e134467d120b40099da16c467dc365e76Andreas Huber
31418da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    mSrcBuffer = new (std::nothrow) uint8_t[max_size];
31428da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    if (mSrcBuffer == NULL) {
31438da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        // file probably specified a bad max size
31448da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        return ERROR_MALFORMED;
31458da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    }
314620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
314720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = true;
314820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
314920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
315020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
315120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
315220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::stop() {
31537b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
31547b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
3155dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
315620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
315720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mBuffer != NULL) {
315820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->release();
315920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
316020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
316120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31620024245e134467d120b40099da16c467dc365e76Andreas Huber    delete[] mSrcBuffer;
31630024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = NULL;
31640024245e134467d120b40099da16c467dc365e76Andreas Huber
316520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    delete mGroup;
316620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = NULL;
316720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
316820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = false;
316920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mCurrentSampleIndex = 0;
317020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
317120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
317220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
317320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
317405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseChunk(off64_t *offset) {
317505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t hdr[2];
317605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
317705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_IO;
317805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
317905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t chunk_size = ntohl(hdr[0]);
318005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t chunk_type = ntohl(hdr[1]);
318105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t data_offset = *offset + 8;
318205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
318305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (chunk_size == 1) {
318405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
318505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_IO;
318605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
318705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        chunk_size = ntoh64(chunk_size);
318805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        data_offset += 8;
318905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
319005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (chunk_size < 16) {
319105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            // The smallest valid chunk is 16 bytes long in this case.
319205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
319305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
319405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (chunk_size < 8) {
319505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // The smallest valid chunk is 8 bytes long.
319605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
319705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
319805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
319905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    char chunk[5];
320005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    MakeFourCCString(chunk_type, chunk);
320105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Source chunk %s @ %llx", chunk, *offset);
320205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
320305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t chunk_data_size = *offset + chunk_size - data_offset;
320405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
320505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    switch(chunk_type) {
320605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
320705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'r', 'a', 'f'):
320805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('m', 'o', 'o', 'f'): {
320905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t stop_offset = *offset + chunk_size;
321005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset = data_offset;
321105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            while (*offset < stop_offset) {
321205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err = parseChunk(offset);
321305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (err != OK) {
321405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return err;
321505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
321605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
321705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
32183f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                // *offset points to the box following this moof. Find the next moof from there.
32193f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen
32203f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                while (true) {
32213f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
32223f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                        return ERROR_END_OF_STREAM;
32233f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    }
32243f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    chunk_size = ntohl(hdr[0]);
32253f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    chunk_type = ntohl(hdr[1]);
32263f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
32273f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                        mNextMoofOffset = *offset;
32283f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                        break;
32293f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    }
32303f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    *offset += chunk_size;
32313f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                }
323205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
323305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
323405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
323505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
323605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'f', 'h', 'd'): {
323705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err;
323805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if ((err = parseTrackFragmentHeader(data_offset, chunk_data_size)) != OK) {
323905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return err;
324005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
324105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                *offset += chunk_size;
324205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                break;
324305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
324405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
324505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'r', 'u', 'n'): {
324605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err;
324705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (mLastParsedTrackId == mTrackId) {
324805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    if ((err = parseTrackFragmentRun(data_offset, chunk_data_size)) != OK) {
324905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        return err;
325005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    }
325105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
325205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
325305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                *offset += chunk_size;
325405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                break;
325505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
325605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3257ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'a', 'i', 'z'): {
3258ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            status_t err;
3259ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((err = parseSampleAuxiliaryInformationSizes(data_offset, chunk_data_size)) != OK) {
3260ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return err;
3261ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3262ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
3263ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
3264ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3265ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'a', 'i', 'o'): {
3266ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            status_t err;
3267ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((err = parseSampleAuxiliaryInformationOffsets(data_offset, chunk_data_size)) != OK) {
3268ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return err;
3269ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3270ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
3271ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
3272ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3273ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3274ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('m', 'd', 'a', 't'): {
3275ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // parse DRM info if present
3276ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("MPEG4Source::parseChunk mdat");
3277ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // if saiz/saoi was previously observed, do something with the sampleinfos
3278ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
3279ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
3280ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3281ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
328205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        default: {
328305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset += chunk_size;
328405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
328505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
328605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
328705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
328805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
328905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
329084333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG4Source::parseSampleAuxiliaryInformationSizes(
329184333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        off64_t offset, off64_t /* size */) {
3292ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("parseSampleAuxiliaryInformationSizes");
3293ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // 14496-12 8.7.12
3294ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t version;
3295ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(
3296ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset, &version, sizeof(version))
3297ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            < (ssize_t)sizeof(version)) {
3298ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3299ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3300ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3301ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (version != 0) {
3302ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_UNSUPPORTED;
3303ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3304ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
3305ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3306ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t flags;
3307ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt24(offset, &flags)) {
3308ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3309ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3310ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 3;
3311ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3312ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (flags & 1) {
3313ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        uint32_t tmp;
3314ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
3315ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_MALFORMED;
3316ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3317ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentAuxInfoType = tmp;
3318ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        offset += 4;
3319ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
3320ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_MALFORMED;
3321ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3322ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentAuxInfoTypeParameter = tmp;
3323ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        offset += 4;
3324ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3325ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3326ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t defsize;
3327ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(offset, &defsize, 1) != 1) {
3328ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_MALFORMED;
3329ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3330ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mCurrentDefaultSampleInfoSize = defsize;
3331ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
3332ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3333ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t smplcnt;
3334ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &smplcnt)) {
3335ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_MALFORMED;
3336ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
333748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    mCurrentSampleInfoCount = smplcnt;
3338ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 4;
3339ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
334048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (mCurrentDefaultSampleInfoSize != 0) {
334148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        ALOGV("@@@@ using default sample info size of %d", mCurrentDefaultSampleInfoSize);
334248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return OK;
334348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
3344ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (smplcnt > mCurrentSampleInfoAllocSize) {
3345ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoSizes = (uint8_t*) realloc(mCurrentSampleInfoSizes, smplcnt);
3346ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoAllocSize = smplcnt;
3347ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3348ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3349ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mDataSource->readAt(offset, mCurrentSampleInfoSizes, smplcnt);
3350ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    return OK;
3351ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen}
3352ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
335384333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(
335484333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        off64_t offset, off64_t /* size */) {
3355ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("parseSampleAuxiliaryInformationOffsets");
3356ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // 14496-12 8.7.13
3357ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t version;
3358ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(offset, &version, sizeof(version)) != 1) {
3359ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3360ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3361ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
3362ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3363ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t flags;
3364ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt24(offset, &flags)) {
3365ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3366ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3367ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 3;
3368ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3369ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t entrycount;
3370ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &entrycount)) {
3371ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3372ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3373ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 4;
3374ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3375ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (entrycount > mCurrentSampleInfoOffsetsAllocSize) {
3376ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoOffsets = (uint64_t*) realloc(mCurrentSampleInfoOffsets, entrycount * 8);
3377ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoOffsetsAllocSize = entrycount;
3378ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3379ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mCurrentSampleInfoOffsetCount = entrycount;
3380ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3381ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < entrycount; i++) {
3382ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (version == 0) {
3383ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t tmp;
3384ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (!mDataSource->getUInt32(offset, &tmp)) {
3385ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
3386ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3387ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mCurrentSampleInfoOffsets[i] = tmp;
3388ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset += 4;
3389ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        } else {
3390ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint64_t tmp;
3391ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (!mDataSource->getUInt64(offset, &tmp)) {
3392ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
3393ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3394ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mCurrentSampleInfoOffsets[i] = tmp;
3395ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset += 8;
3396ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3397ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3398ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3399ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // parse clear/encrypted data
3400ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3401ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    off64_t drmoffset = mCurrentSampleInfoOffsets[0]; // from moof
3402ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3403ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    drmoffset += mCurrentMoofOffset;
3404ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int ivlength;
3405ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    CHECK(mFormat->findInt32(kKeyCryptoDefaultIVSize, &ivlength));
340648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
340748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    // read CencSampleAuxiliaryDataFormats
3408ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mCurrentSampleInfoCount; i++) {
3409ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Sample *smpl = &mCurrentSamples.editItemAt(i);
3410ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3411ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memset(smpl->iv, 0, 16);
3412ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (mDataSource->readAt(drmoffset, smpl->iv, ivlength) != ivlength) {
3413ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_IO;
3414ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3415ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3416ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        drmoffset += ivlength;
3417ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
341848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        int32_t smplinfosize = mCurrentDefaultSampleInfoSize;
341948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        if (smplinfosize == 0) {
342048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smplinfosize = mCurrentSampleInfoSizes[i];
3421ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
342248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        if (smplinfosize > ivlength) {
342348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint16_t numsubsamples;
342448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (!mDataSource->getUInt16(drmoffset, &numsubsamples)) {
3425ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
3426ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3427ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            drmoffset += 2;
342848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            for (size_t j = 0; j < numsubsamples; j++) {
342948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                uint16_t numclear;
343048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                uint32_t numencrypted;
343148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                if (!mDataSource->getUInt16(drmoffset, &numclear)) {
343248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                    return ERROR_IO;
343348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                }
343448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                drmoffset += 2;
343548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                if (!mDataSource->getUInt32(drmoffset, &numencrypted)) {
343648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                    return ERROR_IO;
343748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                }
343848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                drmoffset += 4;
343948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->clearsizes.add(numclear);
344048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->encryptedsizes.add(numencrypted);
3441ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
344248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        } else {
344348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smpl->clearsizes.add(0);
344448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smpl->encryptedsizes.add(smpl->size);
3445ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3446ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3447ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3448ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3449ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    return OK;
3450ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen}
3451ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
345205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentHeader(off64_t offset, off64_t size) {
345305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
345405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 8) {
345505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
345605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
345705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
345805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
3459ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags
346005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
346105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
346205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
346305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & 0xff000000) {
346405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
346505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
346605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
346705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, (uint32_t*)&mLastParsedTrackId)) {
346805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
346905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
347005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
347105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mLastParsedTrackId != mTrackId) {
347205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // this is not the right track, skip it
347305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
347405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
347505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
347605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mFlags = flags;
347705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mTrackID = mLastParsedTrackId;
347805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 8;
347905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 8;
348005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
348105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("fragment header: %08x %08x", flags, mTrackFragmentHeaderInfo.mTrackID);
348205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
348305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent) {
348405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 8) {
348505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
348605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
348705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
348805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset, &mTrackFragmentHeaderInfo.mBaseDataOffset)) {
348905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
349005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
349105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 8;
349205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 8;
349305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
349405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
349505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent) {
349605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
349705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
349805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
349905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
350005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mSampleDescriptionIndex)) {
350105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
350205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
350305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
350405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
350505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
350605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
350705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
350805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
350905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
351005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
351105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
351205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleDuration)) {
351305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
351405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
351505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
351605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
351705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
351805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
351905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
352005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
352105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
352205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
352305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
352405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleSize)) {
352505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
352605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
352705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
352805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
352905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
353005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
353105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
353205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
353305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
353405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
353505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
353605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleFlags)) {
353705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
353805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
353905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
354005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
354105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
354205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
354305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!(flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent)) {
354405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mTrackFragmentHeaderInfo.mBaseDataOffset = mCurrentMoofOffset;
354505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
354605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
354705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mDataOffset = 0;
354805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
354905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
355005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
355105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentRun(off64_t offset, off64_t size) {
355205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
355305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Extractor::parseTrackFragmentRun");
355405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 8) {
355505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
355605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
355705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
355805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    enum {
355905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kDataOffsetPresent                  = 0x01,
356005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kFirstSampleFlagsPresent            = 0x04,
356105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleDurationPresent              = 0x100,
356205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleSizePresent                  = 0x200,
356305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleFlagsPresent                 = 0x400,
356405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleCompositionTimeOffsetPresent = 0x800,
356505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
356605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
356705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
356805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) {
356905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
357005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
357105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("fragment run flags: %08x", flags);
357205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
357305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & 0xff000000) {
357405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
357505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
357605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
357705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if ((flags & kFirstSampleFlagsPresent) && (flags & kSampleFlagsPresent)) {
357805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // These two shall not be used together.
357905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
358005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
358105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
358205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t sampleCount;
358305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, &sampleCount)) {
358405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
358505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
358605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 8;
358705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 8;
358805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
358905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t dataOffset = mTrackFragmentHeaderInfo.mDataOffset;
359005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
359105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t firstSampleFlags = 0;
359205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
359305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kDataOffsetPresent) {
359405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
359505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
359605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
359705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
359805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int32_t dataOffsetDelta;
359905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, (uint32_t*)&dataOffsetDelta)) {
360005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
360105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
360205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
360305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        dataOffset = mTrackFragmentHeaderInfo.mBaseDataOffset + dataOffsetDelta;
360405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
360505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
360605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
360705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
360805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
360905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kFirstSampleFlagsPresent) {
361005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
361105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
361205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
361305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
361405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &firstSampleFlags)) {
361505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
361605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
361705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
361805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
361905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
362005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
362105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t sampleDuration = 0, sampleSize = 0, sampleFlags = 0,
362205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen             sampleCtsOffset = 0;
362305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
362405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size_t bytesPerSample = 0;
362505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleDurationPresent) {
362605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
362705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
362805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
362905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration;
3630c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    } else if (mTrex) {
3631c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        sampleDuration = mTrex->default_sample_duration;
363205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
363305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
363405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleSizePresent) {
363505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
363605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
363705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
363805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
363905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
364005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
364105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
364205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
364305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleFlagsPresent) {
364405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
364505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
364605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
364705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
364805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
364905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
365005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
365105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
365205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleCompositionTimeOffsetPresent) {
365305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
365405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
365505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleCtsOffset = 0;
365605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
365705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3658a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    if (size < (off64_t)sampleCount * bytesPerSample) {
365905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
366005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
366105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
366205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Sample tmp;
366305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    for (uint32_t i = 0; i < sampleCount; ++i) {
366405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleDurationPresent) {
366505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleDuration)) {
366605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
366705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
366805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
366905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
367005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
367105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleSizePresent) {
367205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleSize)) {
367305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
367405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
367505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
367605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
367705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
367805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleFlagsPresent) {
367905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleFlags)) {
368005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
368105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
368205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
368305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
368405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
368505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleCompositionTimeOffsetPresent) {
368605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleCtsOffset)) {
368705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
368805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
368905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
369005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
369105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3692a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("adding sample %d at offset 0x%08" PRIx64 ", size %u, duration %u, "
3693ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen              " flags 0x%08x", i + 1,
369405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dataOffset, sampleSize, sampleDuration,
369505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                (flags & kFirstSampleFlagsPresent) && i == 0
369605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ? firstSampleFlags : sampleFlags);
369705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.offset = dataOffset;
369805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.size = sampleSize;
369905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.duration = sampleDuration;
3700c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        tmp.compositionOffset = sampleCtsOffset;
370105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentSamples.add(tmp);
370205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
370305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        dataOffset += sampleSize;
370405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
370505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
370605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mDataOffset = dataOffset;
370705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
370805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
370905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
371005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
371120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> MPEG4Source::getFormat() {
37127b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
37137b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
371420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return mFormat;
371520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
371620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37176064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const {
37186064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    switch (mNALLengthSize) {
37196064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 1:
37206064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return *data;
37216064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 2:
37226064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U16_AT(data);
37236064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 3:
37246064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return ((size_t)data[0] << 16) | U16_AT(&data[1]);
37256064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 4:
37266064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U32_AT(data);
37276064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
37286064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
37296064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // This cannot happen, mNALLengthSize springs to life by adding 1 to
37306064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // a 2-bit integer.
37316064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    CHECK(!"Should not be here.");
37326064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
37336064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    return 0;
37346064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber}
37356064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
373620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::read(
373720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
37387b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
37397b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
3740dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
374120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
374205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mFirstMoofOffset > 0) {
374305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return fragmentedRead(out, options);
374405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
374505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
374620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *out = NULL;
374720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3748abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    int64_t targetSampleTimeUs = -1;
3749abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
375020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t seekTimeUs;
3751abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
3752abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
3753abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t findFlags = 0;
3754abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        switch (mode) {
3755abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_PREVIOUS_SYNC:
3756abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagBefore;
3757abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3758abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_NEXT_SYNC:
3759abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagAfter;
3760abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3761abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST_SYNC:
3762abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST:
3763abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagClosest;
3764abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3765abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            default:
3766abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                CHECK(!"Should not be here.");
3767abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3768abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3769abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
377020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        uint32_t sampleIndex;
3771abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        status_t err = mSampleTable->findSampleAtTime(
3772599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar                seekTimeUs, 1000000, mTimescale,
3773abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                &sampleIndex, findFlags);
3774abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3775abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
3776abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // We found the closest sample already, now we want the sync
3777abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // sample preceding it (or the sample itself of course), even
3778abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // if the subsequent sync sample is closer.
3779abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            findFlags = SampleTable::kFlagBefore;
3780abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3781abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3782abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleIndex;
3783abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (err == OK) {
3784abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            err = mSampleTable->findSyncSampleNear(
3785abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    sampleIndex, &syncSampleIndex, findFlags);
3786abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
378720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3788788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        uint32_t sampleTime;
3789788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        if (err == OK) {
3790788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber            err = mSampleTable->getMetaDataForSample(
3791788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber                    sampleIndex, NULL, NULL, &sampleTime);
3792788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        }
3793788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber
379420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (err != OK) {
37955295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            if (err == ERROR_OUT_OF_RANGE) {
37965295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // An attempt to seek past the end of the stream would
37975295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // normally cause this ERROR_OUT_OF_RANGE error. Propagating
37985295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // this all the way to the MediaPlayer would cause abnormal
37995295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // termination. Legacy behaviour appears to be to behave as if
38005295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // we had seeked to the end of stream, ending normally.
38015295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                err = ERROR_END_OF_STREAM;
38025295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            }
380305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("end of stream");
380420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return err;
380520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
380620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3807abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
3808abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
3809abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3810abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3811abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#if 0
3812abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleTime;
3813abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
3814abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    syncSampleIndex, NULL, NULL, &syncSampleTime));
3815abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3816df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("seek to time %lld us => sample at time %lld us, "
3817abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             "sync sample at time %lld us",
3818abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             seekTimeUs,
3819abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             sampleTime * 1000000ll / mTimescale,
3820abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             syncSampleTime * 1000000ll / mTimescale);
3821abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#endif
3822abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3823abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        mCurrentSampleIndex = syncSampleIndex;
382420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mBuffer != NULL) {
382520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
382620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
382720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
382820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
382920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // fall through
383020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
383120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3832c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset;
38330024245e134467d120b40099da16c467dc365e76Andreas Huber    size_t size;
3834170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih    uint32_t cts, stts;
38358bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    bool isSyncSample;
3836dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool newBuffer = false;
3837dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (mBuffer == NULL) {
3838dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        newBuffer = true;
383920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3840c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        status_t err =
3841c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber            mSampleTable->getMetaDataForSample(
3842170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                    mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample, &stts);
384320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3844dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
3845dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
3846dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3847dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3848dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        err = mGroup->acquire_buffer(&mBuffer);
3849c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
3850dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
3851ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            CHECK(mBuffer == NULL);
3852dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
3853dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
38540024245e134467d120b40099da16c467dc365e76Andreas Huber    }
385520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
38563b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    if ((!mIsAVC && !mIsHEVC) || mWantsNALFragments) {
3857dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (newBuffer) {
3858dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ssize_t num_bytes_read =
385934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
3860dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3861dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            if (num_bytes_read < (ssize_t)size) {
3862dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer->release();
3863dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer = NULL;
3864dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3865dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                return ERROR_IO;
3866dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            }
3867dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
38687b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber            CHECK(mBuffer != NULL);
3869dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->set_range(0, size);
3870dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->meta_data()->clear();
387148c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mBuffer->meta_data()->setInt64(
38724678a6dc5f09008481524949a9667af5a6190374Andreas Huber                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
3873170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih            mBuffer->meta_data()->setInt64(
3874170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                    kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
3875abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3876abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            if (targetSampleTimeUs >= 0) {
3877abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                mBuffer->meta_data()->setInt64(
3878abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                        kKeyTargetTime, targetSampleTimeUs);
3879abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            }
3880abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
38818bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            if (isSyncSample) {
38828bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
38838bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            }
38848bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
3885dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ++mCurrentSampleIndex;
3886dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3887dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
38883b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        if (!mIsAVC && !mIsHEVC) {
3889dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            *out = mBuffer;
3890dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
3891dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3892dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return OK;
3893dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3894dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3895dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Each NAL unit is split up into its constituent fragments and
3896dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // each one of them returned in its own buffer.
3897dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
38986064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(mBuffer->range_length() >= mNALLengthSize);
3899dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3900dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        const uint8_t *src =
3901dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
3902dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
39036064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t nal_size = parseNALSize(src);
3904e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
390529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("incomplete NAL unit.");
3906e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3907e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer->release();
3908e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer = NULL;
3909e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3910e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            return ERROR_MALFORMED;
3911e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        }
3912dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3913dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        MediaBuffer *clone = mBuffer->clone();
39147b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(clone != NULL);
39156064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
3916dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
39177b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(mBuffer != NULL);
3918dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mBuffer->set_range(
39196064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_offset() + mNALLengthSize + nal_size,
39206064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_length() - mNALLengthSize - nal_size);
3921dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3922dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (mBuffer->range_length() == 0) {
3923dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->release();
3924dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
3925dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3926dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3927dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        *out = clone;
3928dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3929dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        return OK;
3930dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    } else {
3931dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Whole NAL units are returned but each fragment is prefixed by
3932dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // the start code (0x00 00 00 01).
3933dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        ssize_t num_bytes_read = 0;
3934dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        int32_t drm = 0;
3935dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
3936dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (usesDRM) {
3937dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            num_bytes_read =
3938dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
3939dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
3940dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
3941dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
394220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
394320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (num_bytes_read < (ssize_t)size) {
394420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
394520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
394620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3947dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return ERROR_IO;
394820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
394920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3950dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (usesDRM) {
3951dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK(mBuffer != NULL);
3952dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            mBuffer->set_range(0, size);
39536064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
3954dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
3955dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            uint8_t *dstData = (uint8_t *)mBuffer->data();
3956dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size_t srcOffset = 0;
3957dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size_t dstOffset = 0;
3958e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3959dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            while (srcOffset < size) {
396034fe252c89e33572d01fea981b58d7b115e76164James Dong                bool isMalFormed = (srcOffset + mNALLengthSize > size);
396134fe252c89e33572d01fea981b58d7b115e76164James Dong                size_t nalLength = 0;
396234fe252c89e33572d01fea981b58d7b115e76164James Dong                if (!isMalFormed) {
396334fe252c89e33572d01fea981b58d7b115e76164James Dong                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
396434fe252c89e33572d01fea981b58d7b115e76164James Dong                    srcOffset += mNALLengthSize;
396534fe252c89e33572d01fea981b58d7b115e76164James Dong                    isMalFormed = srcOffset + nalLength > size;
396634fe252c89e33572d01fea981b58d7b115e76164James Dong                }
3967e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
396834fe252c89e33572d01fea981b58d7b115e76164James Dong                if (isMalFormed) {
396929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                    ALOGE("Video is malformed");
3970dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    mBuffer->release();
3971dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    mBuffer = NULL;
3972dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return ERROR_MALFORMED;
3973dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
3974dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
3975dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                if (nalLength == 0) {
3976dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    continue;
3977dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
3978dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3979dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                CHECK(dstOffset + 4 <= mBuffer->size());
3980dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3981dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3982dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3983dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3984dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 1;
3985dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
3986dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                srcOffset += nalLength;
3987dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstOffset += nalLength;
3988dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
3989dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK_EQ(srcOffset, size);
3990dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK(mBuffer != NULL);
3991dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            mBuffer->set_range(0, dstOffset);
3992dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3993dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
399420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->meta_data()->clear();
399548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        mBuffer->meta_data()->setInt64(
39964678a6dc5f09008481524949a9667af5a6190374Andreas Huber                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
3997170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih        mBuffer->meta_data()->setInt64(
3998170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
3999abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
4000abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (targetSampleTimeUs >= 0) {
4001abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            mBuffer->meta_data()->setInt64(
4002abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    kKeyTargetTime, targetSampleTimeUs);
4003abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
4004abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
40058bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        if (isSyncSample) {
40068bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
40078bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        }
40088bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
400920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        ++mCurrentSampleIndex;
401020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
401120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        *out = mBuffer;
401220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
401320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
401420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
401520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
401620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
401720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
401805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::fragmentedRead(
401905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MediaBuffer **out, const ReadOptions *options) {
402005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
402105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Source::fragmentedRead");
402205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
402305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    CHECK(mStarted);
402405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
402505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    *out = NULL;
402605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
402705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t targetSampleTimeUs = -1;
402805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
402905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t seekTimeUs;
403005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ReadOptions::SeekMode mode;
403105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
403205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
403305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int numSidxEntries = mSegments.size();
403405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (numSidxEntries != 0) {
403505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            int64_t totalTime = 0;
403605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t totalOffset = mFirstMoofOffset;
403705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            for (int i = 0; i < numSidxEntries; i++) {
403805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                const SidxEntry *se = &mSegments[i];
403905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (totalTime + se->mDurationUs > seekTimeUs) {
404005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    // The requested time is somewhere in this segment
40413f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    if ((mode == ReadOptions::SEEK_NEXT_SYNC && seekTimeUs > totalTime) ||
404205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        (mode == ReadOptions::SEEK_CLOSEST_SYNC &&
404305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        (seekTimeUs - totalTime) > (totalTime + se->mDurationUs - seekTimeUs))) {
404405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        // requested next sync, or closest sync and it was closer to the end of
404505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        // this segment
404605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        totalTime += se->mDurationUs;
404705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        totalOffset += se->mSize;
404805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    }
404905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    break;
405005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
405105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                totalTime += se->mDurationUs;
405205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                totalOffset += se->mSize;
405305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
4054ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentMoofOffset = totalOffset;
4055ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSamples.clear();
4056ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSampleIndex = 0;
4057ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            parseChunk(&totalOffset);
4058ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentTime = totalTime * mTimescale / 1000000ll;
4059ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen        } else {
4060ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            // without sidx boxes, we can only seek to 0
4061ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentMoofOffset = mFirstMoofOffset;
4062ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSamples.clear();
4063ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSampleIndex = 0;
4064ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            off64_t tmp = mCurrentMoofOffset;
4065ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            parseChunk(&tmp);
4066ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentTime = 0;
406705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
406805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
406905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer != NULL) {
407005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
407105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
407205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
407305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
407405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // fall through
407505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
407605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
407705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t offset = 0;
4078442cc6dc48f8188e097617f7f804c314a9dacd0eAndreas Huber    size_t size = 0;
407905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t cts = 0;
408005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    bool isSyncSample = false;
408105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    bool newBuffer = false;
408205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mBuffer == NULL) {
408305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        newBuffer = true;
408405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
408505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mCurrentSampleIndex >= mCurrentSamples.size()) {
40863f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            // move to next fragment if there is one
40873f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            if (mNextMoofOffset <= mCurrentMoofOffset) {
40883f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                return ERROR_END_OF_STREAM;
40893f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            }
4090ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            off64_t nextMoof = mNextMoofOffset;
409105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentMoofOffset = nextMoof;
409205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentSamples.clear();
409305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentSampleIndex = 0;
409405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            parseChunk(&nextMoof);
4095ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            if (mCurrentSampleIndex >= mCurrentSamples.size()) {
4096ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen                return ERROR_END_OF_STREAM;
4097ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            }
409805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
409905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
410005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
410105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset = smpl->offset;
410205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size = smpl->size;
4103c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        cts = mCurrentTime + smpl->compositionOffset;
410405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentTime += smpl->duration;
410505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        isSyncSample = (mCurrentSampleIndex == 0); // XXX
410605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
410705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        status_t err = mGroup->acquire_buffer(&mBuffer);
410805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
410905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (err != OK) {
411005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer == NULL);
411105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("acquire_buffer returned %d", err);
411205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return err;
411305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
411405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
411505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
411648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
411748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    const sp<MetaData> bufmeta = mBuffer->meta_data();
411848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    bufmeta->clear();
411948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (smpl->encryptedsizes.size()) {
412048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // store clear/encrypted lengths in metadata
412148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyPlainSizes, 0,
412248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->clearsizes.array(), smpl->clearsizes.size() * 4);
412348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyEncryptedSizes, 0,
412448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
412548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
412648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
412748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setInt32(kKeyCryptoMode, mCryptoMode);
412848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16);
412948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
413048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
41313b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    if ((!mIsAVC && !mIsHEVC)|| mWantsNALFragments) {
413205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (newBuffer) {
413305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ssize_t num_bytes_read =
413405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
413505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
413605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (num_bytes_read < (ssize_t)size) {
413705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->release();
413805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer = NULL;
413905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
414005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                ALOGV("i/o error");
414105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_IO;
414205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
414305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
414405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
414505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, size);
414605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt64(
414705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
4148170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih            mBuffer->meta_data()->setInt64(
4149170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                    kKeyDuration, ((int64_t)smpl->duration * 1000000) / mTimescale);
415005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
415105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (targetSampleTimeUs >= 0) {
415205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->meta_data()->setInt64(
415305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        kKeyTargetTime, targetSampleTimeUs);
415405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
415505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
415605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (isSyncSample) {
415705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
415805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
415905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
416005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ++mCurrentSampleIndex;
416105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
416205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
41633b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        if (!mIsAVC && !mIsHEVC) {
416405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *out = mBuffer;
416505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
416605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
416705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return OK;
416805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
416905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
417005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // Each NAL unit is split up into its constituent fragments and
417105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // each one of them returned in its own buffer.
417205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
417305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(mBuffer->range_length() >= mNALLengthSize);
417405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
417505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const uint8_t *src =
417605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
417705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
417805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size_t nal_size = parseNALSize(src);
417905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
418005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGE("incomplete NAL unit.");
418105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
418205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
418305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
418405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
418505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
418605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
418705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
418805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MediaBuffer *clone = mBuffer->clone();
418905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(clone != NULL);
419005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
419105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
419205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(mBuffer != NULL);
419305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer->set_range(
419405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->range_offset() + mNALLengthSize + nal_size,
419505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->range_length() - mNALLengthSize - nal_size);
419605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
419705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer->range_length() == 0) {
419805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
419905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
420005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
420105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
420205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        *out = clone;
420305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
420405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
420505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
420605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV("whole NAL");
420705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // Whole NAL units are returned but each fragment is prefixed by
420805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // the start code (0x00 00 00 01).
420905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ssize_t num_bytes_read = 0;
421005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int32_t drm = 0;
421105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
421205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (usesDRM) {
421305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            num_bytes_read =
421405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
421505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else {
421605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
421705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
421805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
421905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (num_bytes_read < (ssize_t)size) {
422005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
422105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
422205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
422305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("i/o error");
422405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_IO;
422505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
422605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
422705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (usesDRM) {
422805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
422905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, size);
423005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
423105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else {
423205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            uint8_t *dstData = (uint8_t *)mBuffer->data();
423305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            size_t srcOffset = 0;
423405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            size_t dstOffset = 0;
423505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
423605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            while (srcOffset < size) {
423705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                bool isMalFormed = (srcOffset + mNALLengthSize > size);
423805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                size_t nalLength = 0;
423905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (!isMalFormed) {
424005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
424105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    srcOffset += mNALLengthSize;
424205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    isMalFormed = srcOffset + nalLength > size;
424305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
424405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
424505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (isMalFormed) {
424605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ALOGE("Video is malformed");
424705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    mBuffer->release();
424805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    mBuffer = NULL;
424905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return ERROR_MALFORMED;
425005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
425105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
425205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (nalLength == 0) {
425305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    continue;
425405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
425505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
425605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                CHECK(dstOffset + 4 <= mBuffer->size());
425705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
425805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
425905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
426005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
426105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 1;
426205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
426305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                srcOffset += nalLength;
426405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstOffset += nalLength;
426505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
426605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK_EQ(srcOffset, size);
426705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
426805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, dstOffset);
426905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
427005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
427105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer->meta_data()->setInt64(
427205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
4273170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih        mBuffer->meta_data()->setInt64(
4274170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                kKeyDuration, ((int64_t)smpl->duration * 1000000) / mTimescale);
427505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
427605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (targetSampleTimeUs >= 0) {
427705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt64(
427805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    kKeyTargetTime, targetSampleTimeUs);
427905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
428005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
428105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (isSyncSample) {
428205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
428305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
428405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
428505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ++mCurrentSampleIndex;
428605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
428705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        *out = mBuffer;
428805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer = NULL;
428905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
429005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
429105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
429205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
429305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
4294bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas HuberMPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix(
4295bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        const char *mimePrefix) {
4296bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    for (Track *track = mFirstTrack; track != NULL; track = track->next) {
4297bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        const char *mime;
4298bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        if (track->meta != NULL
4299bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                && track->meta->findCString(kKeyMIMEType, &mime)
4300bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) {
4301bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber            return track;
4302bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        }
4303bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    }
4304bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber
4305bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    return NULL;
4306bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber}
4307bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber
43081b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool LegacySniffMPEG4(
4309693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
431020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[8];
431120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
431234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    ssize_t n = source->readAt(4, header, sizeof(header));
431320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (n < (ssize_t)sizeof(header)) {
431420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return false;
431520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
431620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
431720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
4318b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8)
4319b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8)
43200dba73763a04d39faf999dcc5ef12af3c99535a7Andreas Huber        || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
4321ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
4322983b449a27b5fa91eca82ede5204b4341899be62Andreas Huber        || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
432318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
43245a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        *confidence = 0.4;
432520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
432620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return true;
432720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
432820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
432920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return false;
433020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
433120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43321b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool isCompatibleBrand(uint32_t fourcc) {
43331b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    static const uint32_t kCompatibleBrands[] = {
43341b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', 'm'),
43351b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', '2'),
43361b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('a', 'v', 'c', '1'),
43373b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        FOURCC('h', 'v', 'c', '1'),
43383b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        FOURCC('h', 'e', 'v', '1'),
43391b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('3', 'g', 'p', '4'),
43401b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '1'),
43411b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '2'),
43424cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong
43434cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        // Won't promise that the following file types can be played.
43444cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        // Just give these file types a chance.
43454cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        FOURCC('q', 't', ' ', ' '),  // Apple's QuickTime
43464cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        FOURCC('M', 'S', 'N', 'V'),  // Sony's PSP
434758fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber
434858fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber        FOURCC('3', 'g', '2', 'a'),  // 3GPP2
434958fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber        FOURCC('3', 'g', '2', 'b'),
43501b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    };
43511b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
43521b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    for (size_t i = 0;
43531b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]);
43541b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         ++i) {
43551b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        if (kCompatibleBrands[i] == fourcc) {
43561b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            return true;
43571b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
43581b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
43591b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
43601b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
43611b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
43621b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
43631b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// Attempt to actually parse the 'ftyp' atom and determine if a suitable
43641b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// compatible brand is present.
4365a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// Also try to identify where this file's metadata ends
4366a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// (end of the 'moov' atom) and report it to the caller as part of
4367a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// the metadata.
43681b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool BetterSniffMPEG4(
4369a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
4370a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        sp<AMessage> *meta) {
4371a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    // We scan up to 128 bytes to identify this file as an MP4.
4372a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    static const off64_t kMaxScanOffset = 128ll;
43731b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4374a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    off64_t offset = 0ll;
4375a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    bool foundGoodFileType = false;
4376a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    off64_t moovAtomEndOffset = -1ll;
4377a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    bool done = false;
43781b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4379a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    while (!done && offset < kMaxScanOffset) {
4380a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint32_t hdr[2];
4381a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        if (source->readAt(offset, hdr, 8) < 8) {
4382a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            return false;
4383a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        }
4384a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4385a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint64_t chunkSize = ntohl(hdr[0]);
4386a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint32_t chunkType = ntohl(hdr[1]);
4387a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        off64_t chunkDataOffset = offset + 8;
4388a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4389a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        if (chunkSize == 1) {
4390a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            if (source->readAt(offset + 8, &chunkSize, 8) < 8) {
43911b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                return false;
43921b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
43931b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4394a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            chunkSize = ntoh64(chunkSize);
4395a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            chunkDataOffset += 8;
4396a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4397a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            if (chunkSize < 16) {
4398a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                // The smallest valid chunk is 16 bytes long in this case.
4399a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                return false;
4400a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            }
4401a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        } else if (chunkSize < 8) {
4402a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            // The smallest valid chunk is 8 bytes long.
4403a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            return false;
4404a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        }
4405a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4406a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        off64_t chunkDataSize = offset + chunkSize - chunkDataOffset;
4407a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
440805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        char chunkstring[5];
440905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MakeFourCCString(chunkType, chunkstring);
4410a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("saw chunk type %s, size %" PRIu64 " @ %lld", chunkstring, chunkSize, offset);
4411a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        switch (chunkType) {
4412a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            case FOURCC('f', 't', 'y', 'p'):
4413a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            {
4414a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                if (chunkDataSize < 8) {
4415a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    return false;
4416a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
4417a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4418a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4;
4419a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
4420a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (i == 1) {
4421a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        // Skip this index, it refers to the minorVersion,
4422a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        // not a brand.
4423a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        continue;
4424a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
4425a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4426a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    uint32_t brand;
4427a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (source->readAt(
4428a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                                chunkDataOffset + 4 * i, &brand, 4) < 4) {
4429a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        return false;
4430a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
4431a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4432a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    brand = ntohl(brand);
4433a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4434a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (isCompatibleBrand(brand)) {
4435a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        foundGoodFileType = true;
4436a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        break;
4437a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
4438a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
4439a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4440a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                if (!foundGoodFileType) {
4441a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    return false;
4442a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
4443a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
44441b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                break;
44451b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
4446a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4447a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            case FOURCC('m', 'o', 'o', 'v'):
4448a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            {
4449a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                moovAtomEndOffset = offset + chunkSize;
4450a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4451a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                done = true;
4452a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                break;
4453a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            }
4454a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4455a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            default:
4456a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                break;
44571b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
4458a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4459a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        offset += chunkSize;
44601b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
44611b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4462a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (!foundGoodFileType) {
44631b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return false;
44641b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
44651b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
44661b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
44675a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber    *confidence = 0.4f;
44681b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4469a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (moovAtomEndOffset >= 0) {
4470a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        *meta = new AMessage;
4471a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        (*meta)->setInt64("meta-data-size", moovAtomEndOffset);
4472a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4473456caf3f5f0af673dc120c17c23635f40d8f5ac2Andreas Huber        ALOGV("found metadata size: %lld", moovAtomEndOffset);
4474a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    }
4475a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
44761b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return true;
44771b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
44781b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
44791b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberbool SniffMPEG4(
44805a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
4481a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        sp<AMessage> *meta) {
4482a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (BetterSniffMPEG4(source, mimeType, confidence, meta)) {
44831b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
44841b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
44851b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
44861b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    if (LegacySniffMPEG4(source, mimeType, confidence)) {
44875ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Identified supported mpeg4 through LegacySniffMPEG4.");
44881b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
44891b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
44901b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
44911b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
44921b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
44931b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
449420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
4495