MPEG4Extractor.cpp revision c9b255b7f771f55462cadd34e109bfee3bf80a3a
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>
36bfed843041b6aaec13ee19996748a7a1476db9c8Lajos Molnar#include <media/stagefright/foundation/AUtils.h>
3720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBufferGroup.h>
3918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/String8.h>
4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
44fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé#include <byteswap.h>
45328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé#include "include/ID3.h"
46fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
4720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Source : public MediaSource {
5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Caller retains ownership of both "dataSource" and "sampleTable".
52942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    MPEG4Source(const sp<MPEG4Extractor> &owner,
53942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen                const sp<MetaData> &format,
54693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber                const sp<DataSource> &dataSource,
5548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                int32_t timeScale,
5605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                const sp<SampleTable> &sampleTable,
5705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                Vector<SidxEntry> &sidx,
58c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                const Trex *trex,
5905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                off64_t firstMoofOffset);
6020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t start(MetaData *params = NULL);
6220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t stop();
6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual sp<MetaData> getFormat();
6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL);
6705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    virtual status_t fragmentedRead(MediaBuffer **buffer, const ReadOptions *options = NULL);
6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
69693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huberprotected:
70693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    virtual ~MPEG4Source();
71693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber
7220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
737b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex mLock;
747b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
75942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    // keep the MPEG4Extractor around, since we're referencing its data
76942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    sp<MPEG4Extractor> mOwner;
7720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mFormat;
78693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<DataSource> mDataSource;
7920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t mTimescale;
80693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<SampleTable> mSampleTable;
8120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t mCurrentSampleIndex;
8205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t mCurrentFragmentIndex;
8305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Vector<SidxEntry> &mSegments;
84c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    const Trex *mTrex;
8505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mFirstMoofOffset;
8605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mCurrentMoofOffset;
8705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mNextMoofOffset;
8805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t mCurrentTime;
8905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int32_t mLastParsedTrackId;
9005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int32_t mTrackId;
9120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
92ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int32_t mCryptoMode;    // passed in from extractor
93ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int32_t mDefaultIVSize; // passed in from extractor
94ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t mCryptoKey[16]; // passed in from extractor
95ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentAuxInfoType;
96ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentAuxInfoTypeParameter;
9748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    int32_t mCurrentDefaultSampleInfoSize;
98ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoCount;
99ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoAllocSize;
100ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t* mCurrentSampleInfoSizes;
101ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoOffsetCount;
102ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoOffsetsAllocSize;
103ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint64_t* mCurrentSampleInfoOffsets;
104ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mIsAVC;
1063b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    bool mIsHEVC;
1076064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    size_t mNALLengthSize;
1086064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
10920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mStarted;
11020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBufferGroup *mGroup;
11220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *mBuffer;
11420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
115dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool mWantsNALFragments;
11620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1170024245e134467d120b40099da16c467dc365e76Andreas Huber    uint8_t *mSrcBuffer;
1180024245e134467d120b40099da16c467dc365e76Andreas Huber
1196064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    size_t parseNALSize(const uint8_t *data) const;
12005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseChunk(off64_t *offset);
12105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseTrackFragmentHeader(off64_t offset, off64_t size);
12205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseTrackFragmentRun(off64_t offset, off64_t size);
123ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    status_t parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size);
124ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    status_t parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size);
12505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
12605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    struct TrackFragmentHeaderInfo {
12705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        enum Flags {
12805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kBaseDataOffsetPresent         = 0x01,
12905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kSampleDescriptionIndexPresent = 0x02,
13005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleDurationPresent  = 0x08,
13105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleSizePresent      = 0x10,
13205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleFlagsPresent     = 0x20,
13305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDurationIsEmpty               = 0x10000,
13405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        };
13505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
13605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mTrackID;
13705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mFlags;
13805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint64_t mBaseDataOffset;
13905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mSampleDescriptionIndex;
14005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleDuration;
14105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleSize;
14205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleFlags;
14305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
14405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint64_t mDataOffset;
14505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
14605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    TrackFragmentHeaderInfo mTrackFragmentHeaderInfo;
14705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
14805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    struct Sample {
14905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t offset;
15005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size_t size;
15105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t duration;
152c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        int32_t compositionOffset;
153ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        uint8_t iv[16];
154ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Vector<size_t> clearsizes;
155ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Vector<size_t> encryptedsizes;
15605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
15705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Vector<Sample> mCurrentSamples;
1586064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
15920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source(const MPEG4Source &);
16020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source &operator=(const MPEG4Source &);
16120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
16220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
16350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This custom data source wraps an existing one and satisfies requests
16450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// falling entirely within a cached range from the cache while forwarding
16550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// all remaining requests to the wrapped datasource.
16650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This is used to cache the full sampletable metadata for a single track,
16750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// possibly wrapping multiple times to cover all tracks, i.e.
16850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// Each MPEG4DataSource caches the sampletable metadata for a single track.
16950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstruct MPEG4DataSource : public DataSource {
17150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource(const sp<DataSource> &source);
17250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual status_t initCheck() const;
174c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
175c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    virtual status_t getSize(off64_t *size);
17650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual uint32_t flags();
17750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
178c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    status_t setCachedRange(off64_t offset, size_t size);
17950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprotected:
18150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual ~MPEG4DataSource();
18250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprivate:
18450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex mLock;
18550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    sp<DataSource> mSource;
187c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t mCachedOffset;
18850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    size_t mCachedSize;
18950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    uint8_t *mCache;
19050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    void clearCache();
19250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource(const MPEG4DataSource &);
19450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource &operator=(const MPEG4DataSource &);
19550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber};
19650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source)
19850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    : mSource(source),
19950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCachedOffset(0),
20050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCachedSize(0),
20150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCache(NULL) {
20250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
20350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
20450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::~MPEG4DataSource() {
20550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    clearCache();
20650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
20750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
20850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Hubervoid MPEG4DataSource::clearCache() {
20950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (mCache) {
21050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        free(mCache);
21150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        mCache = NULL;
21250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
21350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
21450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedOffset = 0;
21550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedSize = 0;
21650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
21750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
21850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstatus_t MPEG4DataSource::initCheck() const {
21950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->initCheck();
22050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
22150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
222c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongssize_t MPEG4DataSource::readAt(off64_t offset, void *data, size_t size) {
22350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex::Autolock autoLock(mLock);
22450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
225bfed843041b6aaec13ee19996748a7a1476db9c8Lajos Molnar    if (isInRange(mCachedOffset, mCachedSize, offset, size)) {
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
506ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar            ALOGE("did not advance: %lld->%lld", (long long)orig_offset, (long long)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
528c9b255b7f771f55462cadd34e109bfee3bf80a3aMarco Nelissen    uint64_t psshsize = 0;
529ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mPssh.size(); i++) {
530ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        psshsize += 20 + mPssh[i].datalen;
531ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
532c9b255b7f771f55462cadd34e109bfee3bf80a3aMarco Nelissen    if (psshsize > 0 && psshsize <= UINT32_MAX) {
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
7428cfad968d5ec429b033caff9743f1ef15090be61Chong Zhangstatic bool underQTMetaPath(const Vector<uint32_t> &path, int32_t depth) {
7438cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    return path.size() >= 2
7448cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            && path[0] == FOURCC('m', 'o', 'o', 'v')
7458cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            && path[1] == FOURCC('m', 'e', 't', 'a')
7468cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            && (depth == 2
7478cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            || (depth == 3
748ef185e94ce624146e3b1f3cbdb2404e833a0f81dChong Zhang                    && (path[2] == FOURCC('h', 'd', 'l', 'r')
749ef185e94ce624146e3b1f3cbdb2404e833a0f81dChong Zhang                    ||  path[2] == FOURCC('i', 'l', 's', 't')
7508cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    ||  path[2] == FOURCC('k', 'e', 'y', 's'))));
7518cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang}
7528cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
75372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber// Given a time in seconds since Jan 1 1904, produce a human-readable string.
75472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic void convertTimeToDate(int64_t time_1904, String8 *s) {
75572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    time_t time_1970 = time_1904 - (((66 * 365 + 17) * 24) * 3600);
75672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
75772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    char tmp[32];
75872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", gmtime(&time_1970));
75972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
76072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    s->setTo(tmp);
76172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
76272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
763c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
764ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar    ALOGV("entering parseChunk %lld/%d", (long long)*offset, depth);
76520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t hdr[2];
76634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_IO;
76820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint64_t chunk_size = ntohl(hdr[0]);
7702d0ac425564ff9882ebaac5267d1a04d4af67d00Bernhard Rosenkränzer    int32_t chunk_type = ntohl(hdr[1]);
771c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t data_offset = *offset + 8;
77220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (chunk_size == 1) {
77434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_IO;
77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
77720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        chunk_size = ntoh64(chunk_size);
77820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        data_offset += 8;
77971b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber
78071b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        if (chunk_size < 16) {
78171b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber            // The smallest valid chunk is 16 bytes long in this case.
78271b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber            return ERROR_MALFORMED;
78371b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        }
784a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen    } else if (chunk_size == 0) {
785a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen        if (depth == 0) {
786a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            // atom extends to end of file
787a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            off64_t sourceSize;
788a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            if (mDataSource->getSize(&sourceSize) == OK) {
789a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen                chunk_size = (sourceSize - *offset);
790a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            } else {
791a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen                // XXX could we just pick a "sufficiently large" value here?
792a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen                ALOGE("atom size is 0, and data source has no size");
793a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen                return ERROR_MALFORMED;
794a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            }
795a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen        } else {
796a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            // not allowed for non-toplevel atoms, skip it
797a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            *offset += 4;
798a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            return OK;
799a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen        }
80071b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber    } else if (chunk_size < 8) {
80171b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        // The smallest valid chunk is 8 bytes long.
802a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGE("invalid chunk size: %" PRIu64, chunk_size);
80371b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        return ERROR_MALFORMED;
80420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
80520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
80620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    char chunk[5];
80720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MakeFourCCString(chunk_type, chunk);
808ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar    ALOGV("chunk: %s @ %lld, %d", chunk, (long long)*offset, depth);
80920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
810b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    if (kUseHexDump) {
811b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        static const char kWhitespace[] = "                                        ";
812b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
813b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        printf("%sfound chunk '%s' of size %" PRIu64 "\n", indent, chunk, chunk_size);
81420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
815b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        char buffer[256];
816b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        size_t n = chunk_size;
817b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        if (n > sizeof(buffer)) {
818b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe            n = sizeof(buffer);
819b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        }
820b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        if (mDataSource->readAt(*offset, buffer, n)
821b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                < (ssize_t)n) {
822b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe            return ERROR_IO;
823b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        }
824ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
825b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        hexdump(buffer, n);
826b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    }
82720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
82872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder autoAdder(&mPath, chunk_type);
82972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
830c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t chunk_data_size = *offset + chunk_size - data_offset;
83120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
83272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (chunk_type != FOURCC('c', 'p', 'r', 't')
833515e855eae78aa495da58356486aaa666cb57fd1James Dong            && chunk_type != FOURCC('c', 'o', 'v', 'r')
83472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            && mPath.size() == 5 && underMetaDataPath(mPath)) {
835c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t stop_offset = *offset + chunk_size;
83672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        *offset = data_offset;
83772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        while (*offset < stop_offset) {
83872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            status_t err = parseChunk(offset, depth + 1);
83972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (err != OK) {
84072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return err;
84172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
84272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
843bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
844bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (*offset != stop_offset) {
845bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
846bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
84772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
84872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return OK;
84972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
85072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
85120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch(chunk_type) {
85220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'v'):
85320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'k'):
85420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'i', 'a'):
85520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'i', 'n', 'f'):
85620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('d', 'i', 'n', 'f'):
85720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'b', 'l'):
85820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'v', 'e', 'x'):
85920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'f'):
86020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'f'):
86120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'f', 'r', 'a'):
86272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('u', 'd', 't', 'a'):
86372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('i', 'l', 's', 't'):
864ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'i', 'n', 'f'):
865ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'c', 'h', 'i'):
8660a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        case FOURCC('e', 'd', 't', 's'):
86720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
868928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang            if (chunk_type == FOURCC('m', 'o', 'o', 'f') && !mMoofFound) {
869928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang                // store the offset of the first segment
870928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang                mMoofFound = true;
871928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang                mMoofOffset = *offset;
872928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang            }
873928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang
87450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
875a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                ALOGV("sampleTable chunk is %" PRIu64 " bytes long.", chunk_size);
87650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
877b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                if (mDataSource->flags()
878b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                        & (DataSource::kWantsPrefetching
879b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                            | DataSource::kIsCachingDataSource)) {
88050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    sp<MPEG4DataSource> cachedSource =
88150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                        new MPEG4DataSource(mDataSource);
88250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
88350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
88450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                        mDataSource = cachedSource;
88550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    }
88650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                }
8871edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber
888f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                if (mLastTrack == NULL)
889f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                    return ERROR_MALFORMED;
890f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
8911edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber                mLastTrack->sampleTable = new SampleTable(mDataSource);
89250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            }
89350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
8946f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber            bool isTrack = false;
895bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (chunk_type == FOURCC('t', 'r', 'a', 'k')) {
8966f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                isTrack = true;
8976f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
898bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                Track *track = new Track;
899bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->next = NULL;
900bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                if (mLastTrack) {
901bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    mLastTrack->next = track;
902bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                } else {
903bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    mFirstTrack = track;
904bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                }
905bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                mLastTrack = track;
906bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
907bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->meta = new MetaData;
908bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->includes_expensive_metadata = false;
9096f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                track->skipTrack = false;
910bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->timescale = 0;
911bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->meta->setCString(kKeyMIMEType, "application/octet-stream");
912bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
913bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
914c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
91520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset;
91620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
91720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
91820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
91920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
92020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
92120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
92220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
923bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
924bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
925bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
926bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
9276f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber            if (isTrack) {
9286f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                if (mLastTrack->skipTrack) {
9296f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    Track *cur = mFirstTrack;
9306f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
9316f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    if (cur == mLastTrack) {
9326f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        delete cur;
9336f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        mFirstTrack = mLastTrack = NULL;
9346f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    } else {
9356f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        while (cur && cur->next != mLastTrack) {
9366f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                            cur = cur->next;
9376f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        }
9386f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        cur->next = NULL;
9396f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        delete mLastTrack;
9406f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        mLastTrack = cur;
9416f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    }
9426f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
9436f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    return OK;
9446f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                }
9456f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
946bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                status_t err = verifyTrack(mLastTrack);
947bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
948bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                if (err != OK) {
949bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    return err;
950bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                }
951bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
952bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                mInitCheck = OK;
95320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
954dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                if (!mIsDrm) {
955dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return UNKNOWN_ERROR;  // Return a dummy error.
956dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                } else {
957dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return OK;
958dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
95920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
96020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
96120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
96220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9630a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        case FOURCC('e', 'l', 's', 't'):
9640a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        {
9650517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
9660517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
9670a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            // See 14496-12 8.6.6
9680a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            uint8_t version;
9690a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (mDataSource->readAt(data_offset, &version, 1) < 1) {
9700a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                return ERROR_IO;
9710a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
9720a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9730a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            uint32_t entry_count;
9740a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (!mDataSource->getUInt32(data_offset + 4, &entry_count)) {
9750a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                return ERROR_IO;
9760a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
9770a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9780a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (entry_count != 1) {
9790a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                // we only support a single entry at the moment, for gapless playback
9800a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                ALOGW("ignoring edit list with %d entries", entry_count);
981fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            } else if (mHeaderTimescale == 0) {
982210efd48ed21ca0084d9440f9a1db7d9878f8094Marco Nelissen                ALOGW("ignoring edit list because timescale is 0");
9830a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            } else {
9840a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                off64_t entriesoffset = data_offset + 8;
9850a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                uint64_t segment_duration;
9860a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int64_t media_time;
9870a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9880a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                if (version == 1) {
9890a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    if (!mDataSource->getUInt64(entriesoffset, &segment_duration) ||
9900a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                            !mDataSource->getUInt64(entriesoffset + 8, (uint64_t*)&media_time)) {
9910a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        return ERROR_IO;
9920a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    }
9930a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                } else if (version == 0) {
9940a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    uint32_t sd;
9950a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int32_t mt;
9960a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    if (!mDataSource->getUInt32(entriesoffset, &sd) ||
9970a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                            !mDataSource->getUInt32(entriesoffset + 4, (uint32_t*)&mt)) {
9980a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        return ERROR_IO;
9990a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    }
10000a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    segment_duration = sd;
10010a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    media_time = mt;
10020a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                } else {
10030a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    return ERROR_IO;
10040a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                }
10050a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
1006fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                uint64_t halfscale = mHeaderTimescale / 2;
1007fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                segment_duration = (segment_duration * 1000000 + halfscale)/ mHeaderTimescale;
1008fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                media_time = (media_time * 1000000 + halfscale) / mHeaderTimescale;
10090a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
10100a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int64_t duration;
10110a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int32_t samplerate;
10121391f933b49cfb56da9aa63f723de83b076cf888Robert Shih                if (!mLastTrack) {
10131391f933b49cfb56da9aa63f723de83b076cf888Robert Shih                    return ERROR_MALFORMED;
10141391f933b49cfb56da9aa63f723de83b076cf888Robert Shih                }
10150a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                if (mLastTrack->meta->findInt64(kKeyDuration, &duration) &&
10160a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        mLastTrack->meta->findInt32(kKeySampleRate, &samplerate)) {
10170a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
10180a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t delay = (media_time  * samplerate + 500000) / 1000000;
10190a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
10200a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
10210a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t paddingus = duration - (segment_duration + media_time);
1022465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                    if (paddingus < 0) {
1023465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        // track duration from media header (which is what kKeyDuration is) might
1024465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        // be slightly shorter than the segment duration, which would make the
1025465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        // padding negative. Clamp to zero.
1026465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        paddingus = 0;
1027465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                    }
10280a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t paddingsamples = (paddingus * samplerate + 500000) / 1000000;
10290a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    mLastTrack->meta->setInt32(kKeyEncoderPadding, paddingsamples);
10300a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                }
10310a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
10320a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            break;
10330a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        }
10340a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
1035ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('f', 'r', 'm', 'a'):
1036ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
10370517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
10380517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
103948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t original_fourcc;
1040ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset, &original_fourcc, 4) < 4) {
1041ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1042ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1043ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            original_fourcc = ntohl(original_fourcc);
1044ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("read original format: %d", original_fourcc);
1045f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
1046f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1047f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1048f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
1049ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc));
105048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t num_channels = 0;
105148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t sample_rate = 0;
105248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (AdjustChannelsAndRate(original_fourcc, &num_channels, &sample_rate)) {
105348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
105448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
105548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            }
1056ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1057ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1058ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1059ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('t', 'e', 'n', 'c'):
1060ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
10610517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
10620517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1063ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (chunk_size < 32) {
1064ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1065ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1066ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1067ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // tenc box contains 1 byte version, 3 byte flags, 3 byte default algorithm id, one byte
1068ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // default IV size, 16 bytes default KeyID
1069ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // (ISO 23001-7)
1070ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            char buf[4];
1071ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memset(buf, 0, 4);
1072ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 4, buf + 1, 3) < 3) {
1073ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1074ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1075ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t defaultAlgorithmId = ntohl(*((int32_t*)buf));
1076ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (defaultAlgorithmId > 1) {
1077ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only 0 (clear) and 1 (AES-128) are valid
1078ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1079ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1080ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1081ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memset(buf, 0, 4);
1082ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 7, buf + 3, 1) < 1) {
1083ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1084ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1085ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t defaultIVSize = ntohl(*((int32_t*)buf));
1086ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1087ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((defaultAlgorithmId == 0 && defaultIVSize != 0) ||
1088ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    (defaultAlgorithmId != 0 && defaultIVSize == 0)) {
1089ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only unencrypted data must have 0 IV size
1090ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1091ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            } else if (defaultIVSize != 0 &&
1092ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    defaultIVSize != 8 &&
1093ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    defaultIVSize != 16) {
1094ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only supported sizes are 0, 8 and 16
1095ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1096ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1097ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1098ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint8_t defaultKeyId[16];
1099ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1100ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 8, &defaultKeyId, 16) < 16) {
1101ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1102ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1103ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1104f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1105f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1106f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
1107ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setInt32(kKeyCryptoMode, defaultAlgorithmId);
1108ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setInt32(kKeyCryptoDefaultIVSize, defaultIVSize);
1109ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setData(kKeyCryptoKey, 'tenc', defaultKeyId, 16);
1110ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1111ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1112ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
111320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'k', 'h', 'd'):
111420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
11150517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
11160517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1117ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            status_t err;
1118ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) {
1119ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber                return err;
112020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
112120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
112220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
112320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
112420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1125ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('p', 's', 's', 'h'):
1126ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
11270517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
11280517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1129ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            PsshInfo pssh;
1130ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1131ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 4, &pssh.uuid, 16) < 16) {
1132ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1133ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1134ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1135ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t psshdatalen = 0;
1136ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 20, &psshdatalen, 4) < 4) {
1137ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1138ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1139ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            pssh.datalen = ntohl(psshdatalen);
1140ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("pssh data size: %d", pssh.datalen);
1141c9b255b7f771f55462cadd34e109bfee3bf80a3aMarco Nelissen            if (chunk_size < 20 || pssh.datalen > chunk_size - 20) {
1142ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // pssh data length exceeds size of containing box
1143ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1144ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1145ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
11468da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            pssh.data = new (std::nothrow) uint8_t[pssh.datalen];
11478da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            if (pssh.data == NULL) {
11488da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen                return ERROR_MALFORMED;
11498da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            }
1150ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("allocated pssh @ %p", pssh.data);
1151ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ssize_t requested = (ssize_t) pssh.datalen;
1152ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 24, pssh.data, requested) < requested) {
1153ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1154ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1155ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mPssh.push_back(pssh);
1156ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1157ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1158ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1159ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
116020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'h', 'd'):
116120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
11620517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
11630517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1164202fbed96db40ec5fb43d633fc97601a15a6dd7aRobert Shih            if (chunk_data_size < 4 || mLastTrack == NULL) {
116520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
116620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
116720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
116820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t version;
116934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
117020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, &version, sizeof(version))
117120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(version)) {
117220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
117320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
117420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1175c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t timescale_offset;
117620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
117720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
117820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 16;
117920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else if (version == 0) {
118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 8;
118120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
118220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
118320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
118420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
118520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t timescale;
118634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
118720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        timescale_offset, &timescale, sizeof(timescale))
118820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(timescale)) {
118920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
119020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
119120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11922e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang            if (!timescale) {
11932e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang                ALOGE("timescale should not be ZERO.");
11942e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang                return ERROR_MALFORMED;
11952e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang            }
11962e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang
119720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->timescale = ntohl(timescale);
119820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1199c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            // 14496-12 says all ones means indeterminate, but some files seem to use
1200c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            // 0 instead. We treat both the same.
120105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            int64_t duration = 0;
120220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
120334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
120420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration, sizeof(duration))
120520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration)) {
120620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
120720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
1208c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (duration != -1) {
1209c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    duration = ntoh64(duration);
1210c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
121120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
121205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t duration32;
121334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
121420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration32, sizeof(duration32))
121520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration32)) {
121620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
121720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
121805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (duration32 != 0xffffffff) {
121905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    duration = ntohl(duration32);
122005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
122120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1222e3e82d54c51a3130badcd9e433fe808d965f15c2Joshua J. Drake            if (duration != 0 && mLastTrack->timescale != 0) {
1223c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mLastTrack->meta->setInt64(
1224c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                        kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
1225c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
122620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12277a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            uint8_t lang[2];
12287a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            off64_t lang_offset;
12297a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            if (version == 1) {
12307a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                lang_offset = timescale_offset + 4 + 8;
12317a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            } else if (version == 0) {
12327a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                lang_offset = timescale_offset + 4 + 4;
12337a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            } else {
12347a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                return ERROR_IO;
12357a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            }
12367a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
12377a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            if (mDataSource->readAt(lang_offset, &lang, sizeof(lang))
12387a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                    < (ssize_t)sizeof(lang)) {
12397a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                return ERROR_IO;
12407a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            }
12417a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
12427a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // To get the ISO-639-2/T three character language code
12437a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // 1 bit pad followed by 3 5-bits characters. Each character
12447a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // is packed as the difference between its ASCII value and 0x60.
12457a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            char lang_code[4];
12467a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[0] = ((lang[0] >> 2) & 0x1f) + 0x60;
12477a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[1] = ((lang[0] & 0x3) << 3 | (lang[1] >> 5)) + 0x60;
12487a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[2] = (lang[1] & 0x1f) + 0x60;
12497a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[3] = '\0';
12507a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
12517a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            mLastTrack->meta->setCString(
12527a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                    kKeyMediaLanguage, lang_code);
12537a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
125420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
125520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
125620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
125720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'd'):
125820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
125920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 8) {
126020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
126120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
126220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
126320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8];
1264c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size < (off64_t)sizeof(buffer)) {
1265bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1266bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
1267bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
126834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
126920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, 8) < 8) {
127020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
127120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
127220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
127320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
127420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
127520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
127620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
127720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
127820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t entry_count = U32_AT(&buffer[4]);
127920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
128020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (entry_count > 1) {
12813b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // For 3GPP timed text, there could be multiple tx3g boxes contain
12823b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // multiple text display formats. These formats will be used to
12833b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // display the timed text.
1284ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // For encrypted files, there may also be more than one entry.
12853b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                const char *mime;
1286f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
1287f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                if (mLastTrack == NULL)
1288f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                    return ERROR_MALFORMED;
1289f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
12903b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1291ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) &&
1292ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                        strcasecmp(mime, "application/octet-stream")) {
12933b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    // For now we only support a single type of media per track.
12943b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    mLastTrack->skipTrack = true;
12953b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    *offset += chunk_size;
12963b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    break;
12973b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                }
129820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1299c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
130020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + 8;
130120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            for (uint32_t i = 0; i < entry_count; ++i) {
130220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
130320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
130420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
130520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
130620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1307bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1308bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1309bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1310bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
131120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
131220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
131320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
131420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
131548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        case FOURCC('e', 'n', 'c', 'a'):
131620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
1317371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
131820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
131920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8 + 20];
132020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
132120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic AudioSampleEntry size.
132220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
132320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
132420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
132534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
132620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
132720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
132820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
132920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1330b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe            uint16_t data_ref_index __unused = U16_AT(&buffer[6]);
133148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t num_channels = U16_AT(&buffer[16]);
133220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
133381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint16_t sample_size = U16_AT(&buffer[18]);
133481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
133581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
1336f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1337f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1338f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
133948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (chunk_type != FOURCC('e', 'n', 'c', 'a')) {
134048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                // if the chunk type is enca, we'll get the type from the sinf/frma box later
134148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
134248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate);
134320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
134448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            ALOGV("*** coding='%s' %d channels, size %d, rate %d\n",
134581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                   chunk, num_channels, sample_size, sample_rate);
134620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
134720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
134820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1349c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
135020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
135120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
135220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
135320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
135420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
135520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1357bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1358bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1359bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1360bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
136120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
136220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
136320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
136420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
1365ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('e', 'n', 'c', 'v'):
136620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
1367e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('H', '2', '6', '3'):
1368e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('h', '2', '6', '3'):
136920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
13703b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'v', 'c', '1'):
13713b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'e', 'v', '1'):
137220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
13737be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber            mHasVideo = true;
13747be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
137520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[78];
137620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
137720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic VideoSampleEntry size.
137820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
137920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
138020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
138134769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
138220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
138320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
138420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
138520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1386b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe            uint16_t data_ref_index __unused = U16_AT(&buffer[6]);
138720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t width = U16_AT(&buffer[6 + 18]);
138820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t height = U16_AT(&buffer[6 + 20]);
138920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1390ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // The video sample is not standard-compliant if it has invalid dimension.
1391a6256238d9015c42129fe43791968768fe501efaJames Dong            // Use some default width and height value, and
1392a6256238d9015c42129fe43791968768fe501efaJames Dong            // let the decoder figure out the actual width and height (and thus
1393a6256238d9015c42129fe43791968768fe501efaJames Dong            // be prepared for INFO_FOMRAT_CHANGED event).
1394a6256238d9015c42129fe43791968768fe501efaJames Dong            if (width == 0)  width  = 352;
1395a6256238d9015c42129fe43791968768fe501efaJames Dong            if (height == 0) height = 288;
1396a6256238d9015c42129fe43791968768fe501efaJames Dong
1397134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            // printf("*** coding='%s' width=%d height=%d\n",
1398134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            //        chunk, width, height);
139920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1400f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1401f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1402f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
1403ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (chunk_type != FOURCC('e', 'n', 'c', 'v')) {
1404ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // if the chunk type is encv, we'll get the type from the sinf/frma box later
1405ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
1406ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
140720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyWidth, width);
140820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyHeight, height);
140920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1410c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
141120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
141220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
141320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
141420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
141520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
141620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
141720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1418bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1419bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1420bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1421bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
142220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
142320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
142420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
142520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'c', 'o'):
142620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('c', 'o', '6', '4'):
142720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1428274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
1429274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake                return ERROR_MALFORMED;
1430274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake
143120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
143220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setChunkOffsetParams(
143320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
143420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14350517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
14360517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
143720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
143820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
143920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
144020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
144120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
144220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
144320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
144420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'c'):
144520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1446274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
1447274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake                return ERROR_MALFORMED;
1448274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake
144920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
145020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleToChunkParams(
145120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
145220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14530517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
14540517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
145520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
145620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
145720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
145820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
145920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
146020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
146120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
146220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'z'):
146320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'z', '2'):
146420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1465274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
1466274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake                return ERROR_MALFORMED;
1467274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake
146820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
146920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleSizeParams(
147020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
147120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14720517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
14730517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
147420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
147520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
147620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
147720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1478738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            size_t max_size;
147949110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            err = mLastTrack->sampleTable->getMaxSampleSize(&max_size);
148049110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber
148149110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            if (err != OK) {
148249110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber                return err;
148349110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            }
1484738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber
148505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (max_size != 0) {
148605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // Assume that a given buffer only contains at most 10 chunks,
148705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // each chunk originally prefixed with a 2 byte length will
148805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
148905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // and thus will grow by 2 bytes per chunk.
149005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
149105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            } else {
149205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // No size was specified. Pick a conservatively large size.
149305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                int32_t width, height;
1494f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                if (!mLastTrack->meta->findInt32(kKeyWidth, &width) ||
1495f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    !mLastTrack->meta->findInt32(kKeyHeight, &height)) {
149605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ALOGE("No width or height, assuming worst case 1080p");
1497f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    width = 1920;
1498f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    height = 1080;
149905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
1500f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar
15014256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen                const char *mime;
15024256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1503f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
1504f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // AVC requires compression ratio of at least 2, and uses
1505f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // macroblocks
1506f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    max_size = ((width + 15) / 16) * ((height + 15) / 16) * 192;
1507f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                } else {
1508f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // For all other formats there is no minimum compression
1509f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // ratio. Use compression ratio of 1.
1510f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    max_size = width * height * 3 / 2;
151105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
1512f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size);
151305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
1514113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong
15154256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            // NOTE: setting another piece of metadata invalidates any pointers (such as the
15164256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            // mimetype) previously obtained, so don't cache them.
1517113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            const char *mime;
1518113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1519113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            // Calculate average frame rate.
1520113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            if (!strncasecmp("video/", mime, 6)) {
1521113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                size_t nSamples = mLastTrack->sampleTable->countSamples();
1522113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                int64_t durationUs;
1523113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                if (mLastTrack->meta->findInt64(kKeyDuration, &durationUs)) {
1524113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                    if (durationUs > 0) {
1525113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                        int32_t frameRate = (nSamples * 1000000LL +
1526113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                                    (durationUs >> 1)) / durationUs;
1527113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                        mLastTrack->meta->setInt32(kKeyFrameRate, frameRate);
1528113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                    }
1529113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                }
1530113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            }
1531113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong
153220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
153320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
153420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
153520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 't', 's'):
153620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1537274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
1538274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake                return ERROR_MALFORMED;
1539274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake
15400517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
15410517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
154220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
154320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setTimeToSampleParams(
154420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
154520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
154620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
154720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
154820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
154920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
155020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
155120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
155220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15534931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        case FOURCC('c', 't', 't', 's'):
15544931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        {
1555274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
1556274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake                return ERROR_MALFORMED;
1557274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake
15580517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
15590517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
15604931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            status_t err =
15614931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                mLastTrack->sampleTable->setCompositionTimeToSampleParams(
15624931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                        data_offset, chunk_data_size);
15634931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
15644931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            if (err != OK) {
15654931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                return err;
15664931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            }
15674931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
15684931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            break;
15694931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        }
15704931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
157120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 's'):
157220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1573274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
1574274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake                return ERROR_MALFORMED;
1575274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake
15760517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
15770517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
157820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
157920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSyncSampleParams(
158020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
158120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
158220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
158320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
158420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
158520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
158620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
158720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
158820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1589afd492436efc7f66b958da14659b52232efa5910Marco Nelissen        // \xA9xyz
1590e1b2ccf317301af42bb4b6631a3bcd7d8f519d00Chih-Hung Hsieh        case FOURCC(0xA9, 'x', 'y', 'z'):
15914948818cb91176df74c972ac27b2f392b5d148bcJames Dong        {
15920517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
15930517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1594afd492436efc7f66b958da14659b52232efa5910Marco Nelissen            // Best case the total data length inside "\xA9xyz" box
1595afd492436efc7f66b958da14659b52232efa5910Marco Nelissen            // would be 8, for instance "\xA9xyz" + "\x00\x04\x15\xc7" + "0+0/",
15964948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // where "\x00\x04" is the text string length with value = 4,
15974948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // "\0x15\xc7" is the language code = en, and "0+0" is a
15984948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // location (string) value with longitude = 0 and latitude = 0.
15994948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (chunk_data_size < 8) {
16004948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_MALFORMED;
16014948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
16024948818cb91176df74c972ac27b2f392b5d148bcJames Dong
16034948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Worst case the location string length would be 18,
16044948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // for instance +90.0000-180.0000, without the trailing "/" and
16054948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // the string length + language code.
16064948818cb91176df74c972ac27b2f392b5d148bcJames Dong            char buffer[18];
16074948818cb91176df74c972ac27b2f392b5d148bcJames Dong
16084948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Substracting 5 from the data size is because the text string length +
16094948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // language code takes 4 bytes, and the trailing slash "/" takes 1 byte.
16104948818cb91176df74c972ac27b2f392b5d148bcJames Dong            off64_t location_length = chunk_data_size - 5;
16114948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (location_length >= (off64_t) sizeof(buffer)) {
16124948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_MALFORMED;
16134948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
16144948818cb91176df74c972ac27b2f392b5d148bcJames Dong
16154948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (mDataSource->readAt(
16164948818cb91176df74c972ac27b2f392b5d148bcJames Dong                        data_offset + 4, buffer, location_length) < location_length) {
16174948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_IO;
16184948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
16194948818cb91176df74c972ac27b2f392b5d148bcJames Dong
16204948818cb91176df74c972ac27b2f392b5d148bcJames Dong            buffer[location_length] = '\0';
16214948818cb91176df74c972ac27b2f392b5d148bcJames Dong            mFileMetaData->setCString(kKeyLocation, buffer);
16224948818cb91176df74c972ac27b2f392b5d148bcJames Dong            break;
16234948818cb91176df74c972ac27b2f392b5d148bcJames Dong        }
16244948818cb91176df74c972ac27b2f392b5d148bcJames Dong
162520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('e', 's', 'd', 's'):
162620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
16270517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
16280517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
162920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
163020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
163120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
163220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
163320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[256];
1634c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size > (off64_t)sizeof(buffer)) {
163520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
163620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
163720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
163834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
163920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
164020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
164120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
164220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
164320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
164420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
164520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
164620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
164720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1648f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1649f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1650f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
165120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
165220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
165320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1654ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            if (mPath.size() >= 2
1655ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
1656ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // Information from the ESDS must be relied on for proper
1657ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // setup of sample rate and channel count for MPEG4 Audio.
1658ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // The generic header appears to only contain generic
1659ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // information...
1660ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1661ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio(
1662ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                        &buffer[4], chunk_data_size - 4);
1663ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1664ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                if (err != OK) {
1665ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    return err;
1666ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                }
1667ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            }
1668ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar            if (mPath.size() >= 2
1669ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                    && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'v')) {
1670ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                // Check if the video is MPEG2
1671ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                ESDS esds(&buffer[4], chunk_data_size - 4);
1672ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar
1673ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                uint8_t objectTypeIndication;
1674ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                if (esds.getObjectTypeIndication(&objectTypeIndication) == OK) {
1675ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                    if (objectTypeIndication >= 0x60 && objectTypeIndication <= 0x65) {
1676ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                        mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG2);
1677ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                    }
1678ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                }
1679ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar            }
168020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
168120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
168220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
168320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', 'C'):
168420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
16850517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
16860517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1687d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson            sp<ABuffer> buffer = new ABuffer(chunk_data_size);
168820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
168934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
1690d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson                        data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
169120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
169220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
169320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1694f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1695f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1696f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
169720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
1698d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson                    kKeyAVCC, kTypeAVCC, buffer->data(), chunk_data_size);
169920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
170020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
170120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
17023b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'v', 'c', 'C'):
17033b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        {
17043b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            sp<ABuffer> buffer = new ABuffer(chunk_data_size);
17053b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
17063b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            if (mDataSource->readAt(
17073b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar                        data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
17083b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar                return ERROR_IO;
17093b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            }
17103b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
1711f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1712f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1713f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
17143b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            mLastTrack->meta->setData(
17153b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar                    kKeyHVCC, kTypeHVCC, buffer->data(), chunk_data_size);
17163b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
17173b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            *offset += chunk_size;
17183b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            break;
17193b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        }
172020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1721244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        case FOURCC('d', '2', '6', '3'):
1722244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        {
17230517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
172417e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            /*
172517e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * d263 contains a fixed 7 bytes part:
172617e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   vendor - 4 bytes
172717e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   version - 1 byte
172817e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   level - 1 byte
172917e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   profile - 1 byte
173017e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * optionally, "d263" box itself may contain a 16-byte
173117e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * bit rate box (bitr)
173217e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   average bit rate - 4 bytes
173317e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   max bit rate - 4 bytes
173417e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             */
173517e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            char buffer[23];
173617e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            if (chunk_data_size != 7 &&
173717e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong                chunk_data_size != 23) {
1738ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar                ALOGE("Incorrect D263 box size %lld", (long long)chunk_data_size);
1739244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                return ERROR_MALFORMED;
1740244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            }
1741244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1742244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            if (mDataSource->readAt(
1743244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                    data_offset, buffer, chunk_data_size) < chunk_data_size) {
1744244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                return ERROR_IO;
1745244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            }
1746244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1747f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1748f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1749f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
1750244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size);
1751244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1752244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            break;
1753244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        }
1754244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
175572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'e', 't', 'a'):
175672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
17578cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            off64_t stop_offset = *offset + chunk_size;
17588cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            *offset = data_offset;
17598cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            bool isParsingMetaKeys = underQTMetaPath(mPath, 2);
17608cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            if (!isParsingMetaKeys) {
17618cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                uint8_t buffer[4];
17628cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                if (chunk_data_size < (off64_t)sizeof(buffer)) {
17638cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    *offset += chunk_size;
17648cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    return ERROR_MALFORMED;
17658cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                }
1766bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
17678cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                if (mDataSource->readAt(
17688cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                            data_offset, buffer, 4) < 4) {
17698cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    *offset += chunk_size;
17708cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    return ERROR_IO;
17718cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                }
177272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
17738cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                if (U32_AT(buffer) != 0) {
17748cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    // Should be version 0, flags 0.
1775ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
17768cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    // If it's not, let's assume this is one of those
17778cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    // apparently malformed chunks that don't have flags
17788cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    // and completely different semantics than what's
17798cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    // in the MPEG4 specs and skip it.
17808cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    *offset += chunk_size;
17818cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    return OK;
17828cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                }
17838cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                *offset +=  sizeof(buffer);
178472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
178572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
178672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            while (*offset < stop_offset) {
178772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                status_t err = parseChunk(offset, depth + 1);
178872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
178972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
179072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
179172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
1792bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1793bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1794bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1795bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
179672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
179772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
179872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
17995d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('m', 'e', 'a', 'n'):
18005d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('n', 'a', 'm', 'e'):
180172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('d', 'a', 't', 'a'):
180272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
18030517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
18040517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
180572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mPath.size() == 6 && underMetaDataPath(mPath)) {
1806fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                status_t err = parseITunesMetaData(data_offset, chunk_data_size);
180772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
180872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
180972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
181072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
181172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
181272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
181372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
181472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
181572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
181672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'v', 'h', 'd'):
181772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
18180517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
18190517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1820c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (chunk_data_size < 32) {
182172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_MALFORMED;
182272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
182372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1824c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            uint8_t header[32];
182572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
182672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, header, sizeof(header))
182772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    < (ssize_t)sizeof(header)) {
182872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
182972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
183072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1831fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            uint64_t creationTime;
1832c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            uint64_t duration = 0;
183372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (header[0] == 1) {
183472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U64_AT(&header[4]);
1835fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                mHeaderTimescale = U32_AT(&header[20]);
1836c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                duration = U64_AT(&header[24]);
1837c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (duration == 0xffffffffffffffff) {
1838c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    duration = 0;
1839c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1840bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (header[0] != 0) {
1841bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
184272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            } else {
184372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U32_AT(&header[4]);
1844fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                mHeaderTimescale = U32_AT(&header[12]);
1845c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                uint32_t d32 = U32_AT(&header[16]);
1846c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (d32 == 0xffffffff) {
1847c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    d32 = 0;
1848c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1849c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                duration = d32;
1850c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1851e3e82d54c51a3130badcd9e433fe808d965f15c2Joshua J. Drake            if (duration != 0 && mHeaderTimescale != 0) {
1852c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mFileMetaData->setInt64(kKeyDuration, duration * 1000000 / mHeaderTimescale);
185372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
185472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
185572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            String8 s;
185672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            convertTimeToDate(creationTime, &s);
185772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
185872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(kKeyDate, s.string());
185972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
186072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
186172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
186272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1863c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        case FOURCC('m', 'e', 'h', 'd'):
1864c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        {
1865c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            *offset += chunk_size;
1866c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1867c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (chunk_data_size < 8) {
1868c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_MALFORMED;
1869c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1870c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1871c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            uint8_t flags[4];
1872c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (mDataSource->readAt(
1873c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                        data_offset, flags, sizeof(flags))
1874c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    < (ssize_t)sizeof(flags)) {
1875c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_IO;
1876c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1877c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1878c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            uint64_t duration = 0;
1879c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (flags[0] == 1) {
1880c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                // 64 bit
1881c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (chunk_data_size < 12) {
1882c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    return ERROR_MALFORMED;
1883c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1884c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mDataSource->getUInt64(data_offset + 4, &duration);
1885c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (duration == 0xffffffffffffffff) {
1886c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    duration = 0;
1887c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1888c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            } else if (flags[0] == 0) {
1889c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                // 32 bit
1890c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                uint32_t d32;
1891c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mDataSource->getUInt32(data_offset + 4, &d32);
1892c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (d32 == 0xffffffff) {
1893c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    d32 = 0;
1894c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1895c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                duration = d32;
1896c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            } else {
1897c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_MALFORMED;
1898c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1899c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1900e3e82d54c51a3130badcd9e433fe808d965f15c2Joshua J. Drake            if (duration != 0 && mHeaderTimescale != 0) {
1901c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mFileMetaData->setInt64(kKeyDuration, duration * 1000000 / mHeaderTimescale);
1902c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1903c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1904c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            break;
1905c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        }
1906c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1907dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        case FOURCC('m', 'd', 'a', 't'):
1908dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        {
1909ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("mdat chunk, drm: %d", mIsDrm);
1910928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang
1911928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang            mMdatFound = true;
1912928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang
1913dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (!mIsDrm) {
1914dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                *offset += chunk_size;
1915dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                break;
1916dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
1917dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
1918dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (chunk_size < 8) {
1919dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
1920dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
1921dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
1922dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return parseDrmSINF(offset, data_offset);
1923dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
1924dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
19253b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        case FOURCC('h', 'd', 'l', 'r'):
19263b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        {
19270517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
19280517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1929ef185e94ce624146e3b1f3cbdb2404e833a0f81dChong Zhang            if (underQTMetaPath(mPath, 3)) {
1930ef185e94ce624146e3b1f3cbdb2404e833a0f81dChong Zhang                break;
1931ef185e94ce624146e3b1f3cbdb2404e833a0f81dChong Zhang            }
1932ef185e94ce624146e3b1f3cbdb2404e833a0f81dChong Zhang
19333b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t buffer;
19343b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (mDataSource->readAt(
19353b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                        data_offset + 8, &buffer, 4) < 4) {
19363b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_IO;
19373b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
19383b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
1939f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1940f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1941f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
19423b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type = ntohl(buffer);
19433b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            // For the 3GPP file format, the handler-type within the 'hdlr' box
1944e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            // shall be 'text'. We also want to support 'sbtl' handler type
1945e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            // for a practical reason as various MPEG4 containers use it.
1946e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            if (type == FOURCC('t', 'e', 'x', 't') || type == FOURCC('s', 'b', 't', 'l')) {
19473b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
19483b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
19493b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
19503b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            break;
19513b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        }
19523b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
19538cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        case FOURCC('k', 'e', 'y', 's'):
19548cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        {
19558cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            *offset += chunk_size;
19568cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
19578cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            if (underQTMetaPath(mPath, 3)) {
19588cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                parseQTMetaKey(data_offset, chunk_data_size);
19598cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            }
19608cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            break;
19618cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        }
19628cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
1963c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        case FOURCC('t', 'r', 'e', 'x'):
1964c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        {
1965c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            *offset += chunk_size;
1966c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1967c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (chunk_data_size < 24) {
1968c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_IO;
1969c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1970c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            Trex trex;
1971c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (!mDataSource->getUInt32(data_offset + 4, &trex.track_ID) ||
1972c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                !mDataSource->getUInt32(data_offset + 8, &trex.default_sample_description_index) ||
1973c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                !mDataSource->getUInt32(data_offset + 12, &trex.default_sample_duration) ||
1974c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                !mDataSource->getUInt32(data_offset + 16, &trex.default_sample_size) ||
1975c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                !mDataSource->getUInt32(data_offset + 20, &trex.default_sample_flags)) {
1976c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_IO;
1977c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1978c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            mTrex.add(trex);
1979c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            break;
1980c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        }
1981c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
19827a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        case FOURCC('t', 'x', '3', 'g'):
19837a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        {
1984f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1985f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1986f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
19873b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type;
19883b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            const void *data;
19893b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            size_t size = 0;
19903b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (!mLastTrack->meta->findData(
19913b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    kKeyTextFormatData, &type, &data, &size)) {
19923b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                size = 0;
19933b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
19943b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
1995dc69f4856187904bfb0d12a72cdf5a563a0deff2Joshua J. Drake            if (SIZE_MAX - chunk_size <= size) {
1996dc69f4856187904bfb0d12a72cdf5a563a0deff2Joshua J. Drake                return ERROR_MALFORMED;
1997dc69f4856187904bfb0d12a72cdf5a563a0deff2Joshua J. Drake            }
1998dc69f4856187904bfb0d12a72cdf5a563a0deff2Joshua J. Drake
19998da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            uint8_t *buffer = new (std::nothrow) uint8_t[size + chunk_size];
20008da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            if (buffer == NULL) {
20018da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen                return ERROR_MALFORMED;
20028da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            }
20033b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
20043b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (size > 0) {
20053b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                memcpy(buffer, data, size);
20063b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
20073b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
20083b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size))
20093b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    < chunk_size) {
20103b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                delete[] buffer;
20113b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                buffer = NULL;
20123b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
20130517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen                // advance read pointer so we don't end up reading this again
20140517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen                *offset += chunk_size;
20153b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_IO;
20163b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
20173b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
20183b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            mLastTrack->meta->setData(
20193b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    kKeyTextFormatData, 0, buffer, size + chunk_size);
20203b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
20213b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            delete[] buffer;
20227a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
20237a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            *offset += chunk_size;
20247a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            break;
20257a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        }
20267a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
2027515e855eae78aa495da58356486aaa666cb57fd1James Dong        case FOURCC('c', 'o', 'v', 'r'):
2028515e855eae78aa495da58356486aaa666cb57fd1James Dong        {
20290517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
20300517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
2031515e855eae78aa495da58356486aaa666cb57fd1James Dong            if (mFileMetaData != NULL) {
2032635bc8f90429b2fdcaf7f8d43f7f59bcd0fe951cDan Albert                ALOGV("chunk_data_size = %" PRId64 " and data_offset = %" PRId64,
2033635bc8f90429b2fdcaf7f8d43f7f59bcd0fe951cDan Albert                      chunk_data_size, data_offset);
20341e51401794ff830c912c21123c321b83c17b491dJoshua J. Drake
2035635bc8f90429b2fdcaf7f8d43f7f59bcd0fe951cDan Albert                if (chunk_data_size < 0 || static_cast<uint64_t>(chunk_data_size) >= SIZE_MAX - 1) {
20361e51401794ff830c912c21123c321b83c17b491dJoshua J. Drake                    return ERROR_MALFORMED;
20371e51401794ff830c912c21123c321b83c17b491dJoshua J. Drake                }
20381552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1);
2039515e855eae78aa495da58356486aaa666cb57fd1James Dong                if (mDataSource->readAt(
20401552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                    data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) {
2041515e855eae78aa495da58356486aaa666cb57fd1James Dong                    return ERROR_IO;
2042515e855eae78aa495da58356486aaa666cb57fd1James Dong                }
2043515e855eae78aa495da58356486aaa666cb57fd1James Dong                const int kSkipBytesOfDataBox = 16;
204497d45dbfdfc9018f1cbf72641c1447ff59431ae3Joshua J. Drake                if (chunk_data_size <= kSkipBytesOfDataBox) {
204597d45dbfdfc9018f1cbf72641c1447ff59431ae3Joshua J. Drake                    return ERROR_MALFORMED;
204697d45dbfdfc9018f1cbf72641c1447ff59431ae3Joshua J. Drake                }
204797d45dbfdfc9018f1cbf72641c1447ff59431ae3Joshua J. Drake
2048515e855eae78aa495da58356486aaa666cb57fd1James Dong                mFileMetaData->setData(
2049515e855eae78aa495da58356486aaa666cb57fd1James Dong                    kKeyAlbumArt, MetaData::TYPE_NONE,
20501552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                    buffer->data() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox);
2051515e855eae78aa495da58356486aaa666cb57fd1James Dong            }
2052515e855eae78aa495da58356486aaa666cb57fd1James Dong
2053515e855eae78aa495da58356486aaa666cb57fd1James Dong            break;
2054515e855eae78aa495da58356486aaa666cb57fd1James Dong        }
2055515e855eae78aa495da58356486aaa666cb57fd1James Dong
2056fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('t', 'i', 't', 'l'):
2057fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('p', 'e', 'r', 'f'):
2058fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'u', 't', 'h'):
2059fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('g', 'n', 'r', 'e'):
2060fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'l', 'b', 'm'):
2061fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('y', 'r', 'r', 'c'):
2062fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
20630517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
20640517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
2065fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            status_t err = parse3GPPMetaData(data_offset, chunk_data_size, depth);
2066fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2067fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (err != OK) {
2068fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                return err;
2069fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2070fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2071fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2072fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2073fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2074328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        case FOURCC('I', 'D', '3', '2'):
2075328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        {
20760517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
20770517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
2078328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            if (chunk_data_size < 6) {
2079328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                return ERROR_MALFORMED;
2080328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            }
2081328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2082328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            parseID3v2MetaData(data_offset + 6);
2083328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2084328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            break;
2085328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        }
2086328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
20875d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('-', '-', '-', '-'):
20885d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        {
20895d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentMean.clear();
20905d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentName.clear();
20915d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentData.clear();
20925d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            *offset += chunk_size;
20935d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            break;
20945d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        }
20955d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen
209605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('s', 'i', 'd', 'x'):
209705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        {
209805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            parseSegmentIndex(data_offset, chunk_data_size);
209905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset += chunk_size;
210005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return UNKNOWN_ERROR; // stop parsing after sidx
210105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
210205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
210320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
210420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
21058cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            // check if we're parsing 'ilst' for meta keys
21068cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            // if so, treat type as a number (key-id).
21078cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            if (underQTMetaPath(mPath, 3)) {
21088cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                parseQTMetaVal(chunk_type, data_offset, chunk_data_size);
21098cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            }
21108cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
211120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
211220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
211320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
211420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
211520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
211620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
211720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
211820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
211905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) {
212005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen  ALOGV("MPEG4Extractor::parseSegmentIndex");
212105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
212205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 12) {
212305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      return -EINVAL;
212405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
212505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
212605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
212705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) {
212805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
212905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
213005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
213105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t version = flags >> 24;
213205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    flags &= 0xffffff;
213305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
213405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx version %d", version);
213505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
213605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t referenceId;
213705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, &referenceId)) {
213805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
213905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
214005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
214105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t timeScale;
214205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 8, &timeScale)) {
214305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
214405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
214505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx refid/timescale: %d/%d", referenceId, timeScale);
2146e3e82d54c51a3130badcd9e433fe808d965f15c2Joshua J. Drake    if (timeScale == 0)
2147e3e82d54c51a3130badcd9e433fe808d965f15c2Joshua J. Drake        return ERROR_MALFORMED;
214805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
214905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t earliestPresentationTime;
215005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t firstOffset;
215105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
215205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 12;
215305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 12;
215405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
215505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (version == 0) {
215605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 8) {
215705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
215805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
215905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t tmp;
216005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
216105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
216205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
216305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        earliestPresentationTime = tmp;
216405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset + 4, &tmp)) {
216505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
216605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
216705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        firstOffset = tmp;
216805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 8;
216905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 8;
217005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
217105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 16) {
217205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
217305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
217405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset, &earliestPresentationTime)) {
217505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
217605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
217705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset + 8, &firstOffset)) {
217805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
217905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
218005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 16;
218105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 16;
218205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
2183a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("sidx pres/off: %" PRIu64 "/%" PRIu64, earliestPresentationTime, firstOffset);
218405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
218505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 4) {
218605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
218705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
218805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
218905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint16_t referenceCount;
219005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt16(offset + 2, &referenceCount)) {
219105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
219205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
219305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 4;
219405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 4;
219505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("refcount: %d", referenceCount);
219605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
219705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < referenceCount * 12) {
219805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
219905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
220005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
220105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t total_duration = 0;
220205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    for (unsigned int i = 0; i < referenceCount; i++) {
220305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t d1, d2, d3;
220405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
220505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &d1) ||     // size
220605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            !mDataSource->getUInt32(offset + 4, &d2) || // duration
220705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            !mDataSource->getUInt32(offset + 8, &d3)) { // flags
220805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
220905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
221005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
221105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (d1 & 0x80000000) {
221205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGW("sub-sidx boxes not supported yet");
221305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
221405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool sap = d3 & 0x80000000;
22153f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen        uint32_t saptype = (d3 >> 28) & 7;
22163f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen        if (!sap || (saptype != 1 && saptype != 2)) {
22173f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            // type 1 and 2 are sync samples
22183f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            ALOGW("not a stream access point, or unsupported type: %08x", d3);
221905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
222005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        total_duration += d2;
222105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 12;
222205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV(" item %d, %08x %08x %08x", i, d1, d2, d3);
222305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        SidxEntry se;
222405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        se.mSize = d1 & 0x7fffffff;
222505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        se.mDurationUs = 1000000LL * d2 / timeScale;
222605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mSidxEntries.add(se);
222705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
222805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2229c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    uint64_t sidxDuration = total_duration * 1000000 / timeScale;
223005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2231f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake    if (mLastTrack == NULL)
2232f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake        return ERROR_MALFORMED;
2233f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
223405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t metaDuration;
223505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mLastTrack->meta->findInt64(kKeyDuration, &metaDuration) || metaDuration == 0) {
2236c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        mLastTrack->meta->setInt64(kKeyDuration, sidxDuration);
223705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
223805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
223905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
224005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
22418cfad968d5ec429b033caff9743f1ef15090be61Chong Zhangstatus_t MPEG4Extractor::parseQTMetaKey(off64_t offset, size_t size) {
22428cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (size < 8) {
22438cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        return ERROR_MALFORMED;
22448cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
22458cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
22468cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    uint32_t count;
22478cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (!mDataSource->getUInt32(offset + 4, &count)) {
22488cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        return ERROR_MALFORMED;
22498cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
22508cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
22518cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (mMetaKeyMap.size() > 0) {
22528cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        ALOGW("'keys' atom seen again, discarding existing entries");
22538cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        mMetaKeyMap.clear();
22548cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
22558cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
22568cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    off64_t keyOffset = offset + 8;
22578cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    off64_t stopOffset = offset + size;
22588cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    for (size_t i = 1; i <= count; i++) {
22598cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        if (keyOffset + 8 > stopOffset) {
22608cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            return ERROR_MALFORMED;
22618cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        }
22628cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
22638cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        uint32_t keySize;
22648cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        if (!mDataSource->getUInt32(keyOffset, &keySize)
22658cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                || keySize < 8
22668cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                || keyOffset + keySize > stopOffset) {
22678cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            return ERROR_MALFORMED;
22688cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        }
22698cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
22708cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        uint32_t type;
22718cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        if (!mDataSource->getUInt32(keyOffset + 4, &type)
22728cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                || type != FOURCC('m', 'd', 't', 'a')) {
22738cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            return ERROR_MALFORMED;
22748cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        }
22758cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
22768cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        keySize -= 8;
22778cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        keyOffset += 8;
22788cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
22798cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        sp<ABuffer> keyData = new ABuffer(keySize);
22808cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        if (keyData->data() == NULL) {
22818cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            return ERROR_MALFORMED;
22828cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        }
22838cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        if (mDataSource->readAt(
22848cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                keyOffset, keyData->data(), keySize) < (ssize_t) keySize) {
22858cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            return ERROR_MALFORMED;
22868cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        }
22878cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
22888cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        AString key((const char *)keyData->data(), keySize);
22898cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        mMetaKeyMap.add(i, key);
22908cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
22918cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        keyOffset += keySize;
22928cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
22938cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    return OK;
22948cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang}
22958cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
22968cfad968d5ec429b033caff9743f1ef15090be61Chong Zhangstatus_t MPEG4Extractor::parseQTMetaVal(
22978cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        int32_t keyId, off64_t offset, size_t size) {
22988cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    ssize_t index = mMetaKeyMap.indexOfKey(keyId);
22998cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (index < 0) {
23008cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        // corresponding key is not present, ignore
23018cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        return ERROR_MALFORMED;
23028cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
230305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
23048cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (size <= 16) {
23058cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        return ERROR_MALFORMED;
23068cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
23078cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    uint32_t dataSize;
23088cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (!mDataSource->getUInt32(offset, &dataSize)
23098cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            || dataSize > size || dataSize <= 16) {
23108cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        return ERROR_MALFORMED;
23118cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
23128cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    uint32_t atomFourCC;
23138cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (!mDataSource->getUInt32(offset + 4, &atomFourCC)
23148cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            || atomFourCC != FOURCC('d', 'a', 't', 'a')) {
23158cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        return ERROR_MALFORMED;
23168cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
23178cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    uint32_t dataType;
23188cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (!mDataSource->getUInt32(offset + 8, &dataType)
23198cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            || ((dataType & 0xff000000) != 0)) {
23208cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        // not well-known type
23218cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        return ERROR_MALFORMED;
23228cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
23238cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
23248cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    dataSize -= 16;
23258cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    offset += 16;
23268cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
23278cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (dataType == 23 && dataSize >= 4) {
23288cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        // BE Float32
23298cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        uint32_t val;
23308cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        if (!mDataSource->getUInt32(offset, &val)) {
23318cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            return ERROR_MALFORMED;
23328cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        }
23338cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        if (!strcasecmp(mMetaKeyMap[index].c_str(), "com.android.capture.fps")) {
23348cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            mFileMetaData->setFloat(kKeyCaptureFramerate, *(float *)&val);
23358cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        }
23368cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    } else {
23378cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        // add more keys if needed
23388cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        ALOGV("ignoring key: type %d, size %d", dataType, dataSize);
23398cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
23408cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
23418cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    return OK;
23428cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang}
234305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2344ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huberstatus_t MPEG4Extractor::parseTrackHeader(
2345c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t data_offset, off64_t data_size) {
2346ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (data_size < 4) {
2347ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_MALFORMED;
2348ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2349ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2350ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint8_t version;
2351ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (mDataSource->readAt(data_offset, &version, 1) < 1) {
2352ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_IO;
2353ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2354ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2355ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    size_t dynSize = (version == 1) ? 36 : 24;
2356ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2357ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint8_t buffer[36 + 60];
2358ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2359c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    if (data_size != (off64_t)dynSize + 60) {
2360ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_MALFORMED;
2361ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2362ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2363ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (mDataSource->readAt(
2364ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber                data_offset, buffer, data_size) < (ssize_t)data_size) {
2365ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_IO;
2366ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2367ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2368b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    uint64_t ctime __unused, mtime __unused, duration __unused;
2369ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t id;
2370ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2371ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (version == 1) {
2372ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        ctime = U64_AT(&buffer[4]);
2373ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mtime = U64_AT(&buffer[12]);
2374ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        id = U32_AT(&buffer[20]);
2375ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        duration = U64_AT(&buffer[28]);
237604022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen    } else if (version == 0) {
2377ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        ctime = U32_AT(&buffer[4]);
2378ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mtime = U32_AT(&buffer[8]);
2379ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        id = U32_AT(&buffer[12]);
2380ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        duration = U32_AT(&buffer[20]);
238104022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen    } else {
238204022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen        return ERROR_UNSUPPORTED;
2383ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2384ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2385f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake    if (mLastTrack == NULL)
2386f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake        return ERROR_MALFORMED;
2387f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
2388ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    mLastTrack->meta->setInt32(kKeyTrackID, id);
2389ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2390ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    size_t matrixOffset = dynSize + 16;
2391ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a00 = U32_AT(&buffer[matrixOffset]);
2392ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a01 = U32_AT(&buffer[matrixOffset + 4]);
2393ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a10 = U32_AT(&buffer[matrixOffset + 12]);
2394ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a11 = U32_AT(&buffer[matrixOffset + 16]);
2395ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2396ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#if 0
2397b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    int32_t dx = U32_AT(&buffer[matrixOffset + 8]);
2398b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    int32_t dy = U32_AT(&buffer[matrixOffset + 20]);
2399b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe
2400df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("x' = %.2f * x + %.2f * y + %.2f",
2401ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber         a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f);
2402df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("y' = %.2f * x + %.2f * y + %.2f",
2403ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber         a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f);
2404ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#endif
2405ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2406ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t rotationDegrees;
2407ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2408ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    static const int32_t kFixedOne = 0x10000;
2409ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) {
2410ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        // Identity, no rotation
2411ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 0;
2412ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) {
2413ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 90;
2414ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) {
2415ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 270;
2416ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) {
2417ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 180;
2418ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else {
24195ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("We only support 0,90,180,270 degree rotation matrices");
2420ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 0;
2421ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2422ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2423ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (rotationDegrees != 0) {
2424ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees);
2425ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2426ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2427b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    // Handle presentation display size, which could be different
2428b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    // from the image size indicated by kKeyWidth and kKeyHeight.
2429ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t width = U32_AT(&buffer[dynSize + 52]);
2430ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t height = U32_AT(&buffer[dynSize + 56]);
2431b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    mLastTrack->meta->setInt32(kKeyDisplayWidth, width >> 16);
2432b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    mLastTrack->meta->setInt32(kKeyDisplayHeight, height >> 16);
2433ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2434ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    return OK;
2435ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber}
2436ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2437fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhéstatus_t MPEG4Extractor::parseITunesMetaData(off64_t offset, size_t size) {
243872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (size < 4) {
243972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_MALFORMED;
244072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
244172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
24428da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    uint8_t *buffer = new (std::nothrow) uint8_t[size + 1];
24438da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    if (buffer == NULL) {
24448da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        return ERROR_MALFORMED;
24458da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    }
244672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (mDataSource->readAt(
244772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                offset, buffer, size) != (ssize_t)size) {
244872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        delete[] buffer;
244972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        buffer = NULL;
245072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
245172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_IO;
245272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
245372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
245472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t flags = U32_AT(buffer);
245572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
245672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t metadataKey = 0;
24575d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    char chunk[5];
24585d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    MakeFourCCString(mPath[4], chunk);
2459ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar    ALOGV("meta: %s @ %lld", chunk, (long long)offset);
24602d0ac425564ff9882ebaac5267d1a04d4af67d00Bernhard Rosenkränzer    switch ((int32_t)mPath[4]) {
246172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'a', 'l', 'b'):
246272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
246372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbum;
246472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
246572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
246672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'A', 'R', 'T'):
246772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
246872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyArtist;
246972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
247072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
247166ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        case FOURCC('a', 'A', 'R', 'T'):
247266ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        {
247366ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            metadataKey = kKeyAlbumArtist;
247466ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            break;
247566ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        }
247672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'd', 'a', 'y'):
247772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
247872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyYear;
247972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
248072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
248172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'n', 'a', 'm'):
248272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
248372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyTitle;
248472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
248572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
248672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'w', 'r', 't'):
248772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
248872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyWriter;
248972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
249072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
249172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('c', 'o', 'v', 'r'):
249272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
249372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbumArt;
249472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
249572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
249672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('g', 'n', 'r', 'e'):
249772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
249872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyGenre;
249972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
250072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
250126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC(0xa9, 'g', 'e', 'n'):
250226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
250326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            metadataKey = kKeyGenre;
250426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
250526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
250611f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        case FOURCC('c', 'p', 'i', 'l'):
250711f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        {
250811f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            if (size == 9 && flags == 21) {
250911f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                char tmp[16];
251011f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                sprintf(tmp, "%d",
251111f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                        (int)buffer[size - 1]);
251211f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen
251311f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                mFileMetaData->setCString(kKeyCompilation, tmp);
251411f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            }
251511f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            break;
251611f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        }
251772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('t', 'r', 'k', 'n'):
251872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
251972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (size == 16 && flags == 0) {
252072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char tmp[16];
2521afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTrack = (uint16_t*)&buffer[10];
2522afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTotalTracks = (uint16_t*)&buffer[12];
2523afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                sprintf(tmp, "%d/%d", ntohs(*pTrack), ntohs(*pTotalTracks));
252472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
252572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
252672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
252772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
252872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
252926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC('d', 'i', 's', 'k'):
253026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
2531afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik            if ((size == 14 || size == 16) && flags == 0) {
253226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                char tmp[16];
2533afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pDisc = (uint16_t*)&buffer[10];
2534afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTotalDiscs = (uint16_t*)&buffer[12];
2535afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                sprintf(tmp, "%d/%d", ntohs(*pDisc), ntohs(*pTotalDiscs));
253626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
253726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(kKeyDiscNumber, tmp);
253826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            }
253926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
254026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
25415d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('-', '-', '-', '-'):
25425d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        {
25435d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            buffer[size] = '\0';
25445d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            switch (mPath[5]) {
25455d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('m', 'e', 'a', 'n'):
25465d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentMean.setTo((const char *)buffer + 4);
25475d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
25485d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('n', 'a', 'm', 'e'):
25495d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentName.setTo((const char *)buffer + 4);
25505d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
25515d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('d', 'a', 't', 'a'):
25525d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentData.setTo((const char *)buffer + 8);
25535d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
25545d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            }
25558c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
25568c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // Once we have a set of mean/name/data info, go ahead and process
25578c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // it to see if its something we are interested in.  Whether or not
25588c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // were are interested in the specific tag, make sure to clear out
25598c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // the set so we can be ready to process another tuple should one
25608c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // show up later in the file.
25618c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            if ((mLastCommentMean.length() != 0) &&
25628c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                (mLastCommentName.length() != 0) &&
25638c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                (mLastCommentData.length() != 0)) {
25648c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
25658c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                if (mLastCommentMean == "com.apple.iTunes"
25668c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        && mLastCommentName == "iTunSMPB") {
25678c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    int32_t delay, padding;
25688c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    if (sscanf(mLastCommentData,
25698c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                               " %*x %x %x %*x", &delay, &padding) == 2) {
2570f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                        if (mLastTrack == NULL)
2571f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                            return ERROR_MALFORMED;
2572f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
25738c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
25748c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        mLastTrack->meta->setInt32(kKeyEncoderPadding, padding);
25758c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    }
25765d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                }
25778c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
25785d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentMean.clear();
25795d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentName.clear();
25805d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentData.clear();
25815d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            }
25825d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            break;
25835d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        }
258426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
258572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        default:
258672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
258772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
258872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
2589328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    if (size >= 8 && metadataKey && !mFileMetaData->hasData(metadataKey)) {
259072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        if (metadataKey == kKeyAlbumArt) {
259172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setData(
259272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    kKeyAlbumArt, MetaData::TYPE_NONE,
259372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    buffer + 8, size - 8);
259472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else if (metadataKey == kKeyGenre) {
259572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (flags == 0) {
259626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // uint8_t genre code, iTunes genre codes are
259726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // the standard id3 codes, except they start
259826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // at 1 instead of 0 (e.g. Pop is 14, not 13)
259926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // We use standard id3 numbering, so subtract 1.
260026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                int genrecode = (int)buffer[size - 1];
260126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                genrecode--;
260226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                if (genrecode < 0) {
260326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                    genrecode = 255; // reserved for 'unknown genre'
260426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                }
260572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char genre[10];
260626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                sprintf(genre, "%d", genrecode);
260772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
260872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(metadataKey, genre);
260926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            } else if (flags == 1) {
261026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // custom genre string
261126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                buffer[size] = '\0';
261226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
261326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(
261426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                        metadataKey, (const char *)buffer + 8);
261572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
261672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else {
261772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            buffer[size] = '\0';
261872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
261972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(
262072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    metadataKey, (const char *)buffer + 8);
262172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
262272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
262372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
262472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    delete[] buffer;
262572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    buffer = NULL;
262672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
262772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return OK;
262872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
262972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
2630fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhéstatus_t MPEG4Extractor::parse3GPPMetaData(off64_t offset, size_t size, int depth) {
26315cea0155cfc41f67e91343c342f44251c03fde3aJoshua J. Drake    if (size < 4 || size == SIZE_MAX) {
2632fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        return ERROR_MALFORMED;
2633fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2634fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
26355cea0155cfc41f67e91343c342f44251c03fde3aJoshua J. Drake    uint8_t *buffer = new (std::nothrow) uint8_t[size + 1];
26368da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    if (buffer == NULL) {
26378da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        return ERROR_MALFORMED;
26388da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    }
2639fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    if (mDataSource->readAt(
2640fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                offset, buffer, size) != (ssize_t)size) {
2641fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        delete[] buffer;
2642fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        buffer = NULL;
2643fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2644fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        return ERROR_IO;
2645fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2646fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2647fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    uint32_t metadataKey = 0;
2648fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    switch (mPath[depth]) {
2649fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('t', 'i', 't', 'l'):
2650fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2651fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyTitle;
2652fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2653fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2654fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('p', 'e', 'r', 'f'):
2655fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2656fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyArtist;
2657fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2658fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2659fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'u', 't', 'h'):
2660fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2661fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyWriter;
2662fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2663fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2664fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('g', 'n', 'r', 'e'):
2665fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2666fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyGenre;
2667fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2668fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2669fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'l', 'b', 'm'):
2670fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2671fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (buffer[size - 1] != '\0') {
2672fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé              char tmp[4];
2673fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé              sprintf(tmp, "%u", buffer[size - 1]);
2674fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2675fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé              mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
2676fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2677fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2678fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyAlbum;
2679fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2680fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2681fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('y', 'r', 'r', 'c'):
2682fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2683fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            char tmp[5];
2684fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            uint16_t year = U16_AT(&buffer[4]);
2685fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2686fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (year < 10000) {
2687fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                sprintf(tmp, "%u", year);
2688fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2689fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                mFileMetaData->setCString(kKeyYear, tmp);
2690fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2691fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2692fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2693fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2694fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        default:
2695fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2696fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2697fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2698fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    if (metadataKey > 0) {
2699fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        bool isUTF8 = true; // Common case
2700fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        char16_t *framedata = NULL;
2701fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        int len16 = 0; // Number of UTF-16 characters
2702fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2703fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        // smallest possible valid UTF-16 string w BOM: 0xfe 0xff 0x00 0x00
27049458e715d391ee8fe455fc31f07ff35ce12e0531Joshua J. Drake        if (size < 6) {
27059458e715d391ee8fe455fc31f07ff35ce12e0531Joshua J. Drake            return ERROR_MALFORMED;
27069458e715d391ee8fe455fc31f07ff35ce12e0531Joshua J. Drake        }
27079458e715d391ee8fe455fc31f07ff35ce12e0531Joshua J. Drake
2708fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        if (size - 6 >= 4) {
2709fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            len16 = ((size - 6) / 2) - 1; // don't include 0x0000 terminator
2710fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            framedata = (char16_t *)(buffer + 6);
2711fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (0xfffe == *framedata) {
2712fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                // endianness marker (BOM) doesn't match host endianness
2713fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                for (int i = 0; i < len16; i++) {
2714fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                    framedata[i] = bswap_16(framedata[i]);
2715fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                }
2716fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                // BOM is now swapped to 0xfeff, we will execute next block too
2717fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2718fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2719fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (0xfeff == *framedata) {
2720fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                // Remove the BOM
2721fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                framedata++;
2722fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                len16--;
2723fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                isUTF8 = false;
2724fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2725fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // else normal non-zero-length UTF-8 string
2726fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // we can't handle UTF-16 without BOM as there is no other
2727fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // indication of encoding.
2728fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2729fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2730fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        if (isUTF8) {
27315cea0155cfc41f67e91343c342f44251c03fde3aJoshua J. Drake            buffer[size] = 0;
2732fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            mFileMetaData->setCString(metadataKey, (const char *)buffer + 6);
2733fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        } else {
2734fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // Convert from UTF-16 string to UTF-8 string.
2735fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            String8 tmpUTF8str(framedata, len16);
2736fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            mFileMetaData->setCString(metadataKey, tmpUTF8str.string());
2737fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2738fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2739fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2740fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    delete[] buffer;
2741fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    buffer = NULL;
2742fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2743fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    return OK;
2744fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé}
2745fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2746328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhévoid MPEG4Extractor::parseID3v2MetaData(off64_t offset) {
2747328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    ID3 id3(mDataSource, true /* ignorev1 */, offset);
2748328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2749328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    if (id3.isValid()) {
2750328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        struct Map {
2751328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            int key;
2752328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            const char *tag1;
2753328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            const char *tag2;
2754328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        };
2755328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        static const Map kMap[] = {
2756328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyAlbum, "TALB", "TAL" },
2757328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyArtist, "TPE1", "TP1" },
2758328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyAlbumArtist, "TPE2", "TP2" },
2759328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyComposer, "TCOM", "TCM" },
2760328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyGenre, "TCON", "TCO" },
2761328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyTitle, "TIT2", "TT2" },
2762328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyYear, "TYE", "TYER" },
2763328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyAuthor, "TXT", "TEXT" },
2764328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyCDTrackNumber, "TRK", "TRCK" },
2765328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyDiscNumber, "TPA", "TPOS" },
2766328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyCompilation, "TCP", "TCMP" },
2767328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        };
2768328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
2769328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2770328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        for (size_t i = 0; i < kNumMapEntries; ++i) {
2771328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            if (!mFileMetaData->hasData(kMap[i].key)) {
2772328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                ID3::Iterator *it = new ID3::Iterator(id3, kMap[i].tag1);
2773328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                if (it->done()) {
2774328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    delete it;
2775328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    it = new ID3::Iterator(id3, kMap[i].tag2);
2776328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                }
2777328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2778328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                if (it->done()) {
2779328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    delete it;
2780328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    continue;
2781328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                }
2782328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2783328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                String8 s;
2784328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                it->getString(&s);
2785328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                delete it;
2786328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2787328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                mFileMetaData->setCString(kMap[i].key, s);
2788328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            }
2789328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        }
2790328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2791328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        size_t dataSize;
2792328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        String8 mime;
2793328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        const void *data = id3.getAlbumArt(&dataSize, &mime);
2794328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2795328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        if (data) {
2796328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            mFileMetaData->setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize);
2797328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            mFileMetaData->setCString(kKeyAlbumArtMIME, mime.string());
2798328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        }
2799328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    }
2800328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé}
2801328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2802693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
280320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
280420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
2805693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return NULL;
280620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
280720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
280820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
280920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
281020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
2811693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber            return NULL;
281220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
281320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
281420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
281520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
281620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
281720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2818371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
2819371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
2820371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
2821371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
2822c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
2823c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    Trex *trex = NULL;
2824c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    int32_t trackId;
2825c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    if (track->meta->findInt32(kKeyTrackID, &trackId)) {
2826c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        for (size_t i = 0; i < mTrex.size(); i++) {
2827c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            Trex *t = &mTrex.editItemAt(index);
2828c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (t->track_ID == (uint32_t) trackId) {
2829c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                trex = t;
2830c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                break;
2831c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
2832c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        }
2833c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    }
2834c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
2835a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("getTrack called, pssh: %zu", mPssh.size());
2836ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2837942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    return new MPEG4Source(this,
283805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            track->meta, mDataSource, track->timescale, track->sampleTable,
2839c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            mSidxEntries, trex, mMoofOffset);
284020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
284120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2842bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber// static
2843bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) {
2844bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const char *mime;
2845bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    CHECK(track->meta->findCString(kKeyMIMEType, &mime));
2846bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2847bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    uint32_t type;
2848bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const void *data;
2849bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    size_t size;
2850bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
2851bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyAVCC, &type, &data, &size)
2852bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeAVCC) {
2853bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
2854bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
28553b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
28563b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        if (!track->meta->findData(kKeyHVCC, &type, &data, &size)
28573b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar                    || type != kTypeHVCC) {
28583b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            return ERROR_MALFORMED;
28593b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        }
2860bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
2861ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar            || !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG2)
2862bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
2863bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyESDS, &type, &data, &size)
2864bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeESDS) {
2865bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
2866bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
2867bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    }
2868bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2869ce171998009e1abcb0c718c0aee495fcd33645e2Robert Shih    if (track->sampleTable == NULL || !track->sampleTable->isValid()) {
2870169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        // Make sure we have all the metadata we need.
2871ce171998009e1abcb0c718c0aee495fcd33645e2Robert Shih        ALOGE("stbl atom missing/invalid.");
2872169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        return ERROR_MALFORMED;
2873169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber    }
2874169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber
28752e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang    if (track->timescale == 0) {
28762e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang        ALOGE("timescale invalid.");
28772e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang        return ERROR_MALFORMED;
28782e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang    }
28792e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang
2880bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    return OK;
2881bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber}
2882bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2883f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivitypedef enum {
2884f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_NONE             = -1,
2885f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_NULL_OBJECT      = 0,
2886f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_MAIN         = 1, /**< Main profile                              */
2887f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_AAC_LC           = 2,   /**< Low Complexity object                     */
2888f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_SSR          = 3,
2889f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_LTP          = 4,
2890f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_SBR              = 5,
2891f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_SCAL         = 6,
2892f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_TWIN_VQ          = 7,
2893f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_CELP             = 8,
2894f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_HVXC             = 9,
2895f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_10          = 10, /**< (reserved)                                */
2896f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_11          = 11, /**< (reserved)                                */
2897f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_TTSI             = 12, /**< TTSI Object                               */
2898f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MAIN_SYNTH       = 13, /**< Main Synthetic object                     */
2899f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_WAV_TAB_SYNTH    = 14, /**< Wavetable Synthesis object                */
2900f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_GEN_MIDI         = 15, /**< General MIDI object                       */
2901f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ALG_SYNTH_AUD_FX = 16, /**< Algorithmic Synthesis and Audio FX object */
2902f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_AAC_LC        = 17,   /**< Error Resilient(ER) AAC Low Complexity    */
2903f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_18          = 18, /**< (reserved)                                */
2904f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_AAC_LTP       = 19, /**< Error Resilient(ER) AAC LTP object        */
2905f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_AAC_SCAL      = 20,   /**< Error Resilient(ER) AAC Scalable object   */
2906f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_TWIN_VQ       = 21, /**< Error Resilient(ER) TwinVQ object         */
2907f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_BSAC          = 22,   /**< Error Resilient(ER) BSAC object           */
2908f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_AAC_LD        = 23,   /**< Error Resilient(ER) AAC LowDelay object   */
2909f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_CELP          = 24, /**< Error Resilient(ER) CELP object           */
2910f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_HVXC          = 25, /**< Error Resilient(ER) HVXC object           */
2911f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_HILN          = 26, /**< Error Resilient(ER) HILN object           */
2912f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_PARA          = 27, /**< Error Resilient(ER) Parametric object     */
2913f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_28          = 28, /**< might become SSC                          */
2914f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_PS               = 29,   /**< PS, Parametric Stereo (includes SBR)      */
2915f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MPEGS            = 30, /**< MPEG Surround                             */
2916f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2917f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ESCAPE           = 31,   /**< Signal AOT uses more than 5 bits          */
2918f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2919f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MP3ONMP4_L1      = 32, /**< MPEG-Layer1 in mp4                        */
2920f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MP3ONMP4_L2      = 33, /**< MPEG-Layer2 in mp4                        */
2921f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MP3ONMP4_L3      = 34, /**< MPEG-Layer3 in mp4                        */
2922f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_35          = 35, /**< might become DST                          */
2923f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_36          = 36, /**< might become ALS                          */
2924f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_SLS          = 37, /**< AAC + SLS                                 */
2925f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_SLS              = 38, /**< SLS                                       */
2926f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_AAC_ELD       = 39, /**< AAC Enhanced Low Delay                    */
2927f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2928f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_USAC             = 42, /**< USAC                                      */
2929f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_SAOC             = 43, /**< SAOC                                      */
2930f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_LD_MPEGS         = 44, /**< Low Delay MPEG Surround                   */
2931f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2932f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD50           = 50,  /**< Interim AOT for Rsvd50                   */
2933f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi} AUDIO_OBJECT_TYPE;
2934f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2935ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
2936ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        const void *esds_data, size_t esds_size) {
2937ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    ESDS esds(esds_data, esds_size);
293881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
293981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    uint8_t objectTypeIndication;
294081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
294181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return ERROR_MALFORMED;
294281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
294381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
294481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (objectTypeIndication == 0xe1) {
294581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        // This isn't MPEG4 audio at all, it's QCELP 14k...
2946f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake        if (mLastTrack == NULL)
2947f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            return ERROR_MALFORMED;
2948f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
294981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
295081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return OK;
295181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
295281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
2953633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong    if (objectTypeIndication  == 0x6b) {
2954633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // The media subtype is MP3 audio
2955633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // Our software MP3 audio decoder may not be able to handle
2956633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // packetized MP3 audio; for now, lets just return ERROR_UNSUPPORTED
295729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("MP3 track in MP4/3GPP file is not supported");
2958633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        return ERROR_UNSUPPORTED;
2959633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong    }
2960633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong
2961ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    const uint8_t *csd;
2962ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    size_t csd_size;
2963ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (esds.getCodecSpecificInfo(
2964ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                (const void **)&csd, &csd_size) != OK) {
2965ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
2966ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2967ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2968b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    if (kUseHexDump) {
2969ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar        printf("ESD of size %zu\n", csd_size);
2970b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        hexdump(csd, csd_size);
2971b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    }
2972ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2973a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    if (csd_size == 0) {
2974a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // There's no further information, i.e. no codec specific data
2975a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // Let's assume that the information provided in the mpeg4 headers
2976a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // is accurate and hope for the best.
2977a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
2978a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        return OK;
2979a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    }
2980a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
2981ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (csd_size < 2) {
2982ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
2983ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2984ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
298500307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent    static uint32_t kSamplingRate[] = {
298600307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
298700307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        16000, 12000, 11025, 8000, 7350
298800307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent    };
298900307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent
2990aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    ABitReader br(csd, csd_size);
2991aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    uint32_t objectType = br.getBits(5);
2992ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2993aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    if (objectType == 31) {  // AAC-ELD => additional 6 bits
2994aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        objectType = 32 + br.getBits(6);
2995ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2996ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2997f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake    if (mLastTrack == NULL)
2998f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake        return ERROR_MALFORMED;
2999f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
3000db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent    //keep AOT type
3001db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent    mLastTrack->meta->setInt32(kKeyAACAOT, objectType);
3002db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent
3003aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    uint32_t freqIndex = br.getBits(4);
3004aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
3005ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t sampleRate = 0;
3006ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t numChannels = 0;
3007ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (freqIndex == 15) {
3008ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        if (csd_size < 5) {
3009ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            return ERROR_MALFORMED;
3010ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
3011aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        sampleRate = br.getBits(24);
3012aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        numChannels = br.getBits(4);
3013ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    } else {
3014595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen        numChannels = br.getBits(4);
301500307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent
301600307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        if (freqIndex == 13 || freqIndex == 14) {
301700307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            return ERROR_MALFORMED;
3018ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
3019ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
302000307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        sampleRate = kSamplingRate[freqIndex];
302100307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent    }
3022595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen
3023f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    if (objectType == AOT_SBR || objectType == AOT_PS) {//SBR specific config per 14496-3 table 1.13
302400307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        uint32_t extFreqIndex = br.getBits(4);
3025b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        int32_t extSampleRate __unused;
302600307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        if (extFreqIndex == 15) {
302700307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            if (csd_size < 8) {
3028595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen                return ERROR_MALFORMED;
3029595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen            }
303000307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            extSampleRate = br.getBits(24);
303100307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        } else {
303200307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            if (extFreqIndex == 13 || extFreqIndex == 14) {
303300307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent                return ERROR_MALFORMED;
303400307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            }
303500307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            extSampleRate = kSamplingRate[extFreqIndex];
3036595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen        }
303700307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        //TODO: save the extension sampling rate value in meta data =>
303800307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        //      mLastTrack->meta->setInt32(kKeyExtSampleRate, extSampleRate);
3039ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
3040ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3041f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    switch (numChannels) {
3042f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        // values defined in 14496-3_2009 amendment-4 Table 1.19 - Channel Configuration
3043f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 0:
3044f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 1:// FC
3045f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 2:// FL FR
3046f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 3:// FC, FL FR
3047f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 4:// FC, FL FR, RC
3048f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 5:// FC, FL FR, SL SR
3049f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 6:// FC, FL FR, SL SR, LFE
3050f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            //numChannels already contains the right value
3051f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            break;
3052f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 11:// FC, FL FR, SL SR, RC, LFE
3053f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            numChannels = 7;
3054f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            break;
3055f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 7: // FC, FCL FCR, FL FR, SL SR, LFE
3056f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 12:// FC, FL  FR,  SL SR, RL RR, LFE
3057f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 14:// FC, FL  FR,  SL SR, LFE, FHL FHR
3058f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            numChannels = 8;
3059f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            break;
3060f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        default:
3061f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            return ERROR_UNSUPPORTED;
3062f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    }
3063f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3064f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    {
3065f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        if (objectType == AOT_SBR || objectType == AOT_PS) {
3066f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            objectType = br.getBits(5);
3067f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3068f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            if (objectType == AOT_ESCAPE) {
3069f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                objectType = 32 + br.getBits(6);
3070f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            }
3071f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        }
3072f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        if (objectType == AOT_AAC_LC || objectType == AOT_ER_AAC_LC ||
3073f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                objectType == AOT_ER_AAC_LD || objectType == AOT_ER_AAC_SCAL ||
3074f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                objectType == AOT_ER_BSAC) {
3075b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe            const int32_t frameLengthFlag __unused = br.getBits(1);
3076f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3077f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            const int32_t dependsOnCoreCoder = br.getBits(1);
3078f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3079f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            if (dependsOnCoreCoder ) {
3080b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                const int32_t coreCoderDelay __unused = br.getBits(14);
3081f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            }
3082f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
308345452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            int32_t extensionFlag = -1;
308445452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            if (br.numBitsLeft() > 0) {
308545452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                extensionFlag = br.getBits(1);
308645452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            } else {
308745452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                switch (objectType) {
308845452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                // 14496-3 4.5.1.1 extensionFlag
308945452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_AAC_LC:
309045452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    extensionFlag = 0;
309145452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    break;
309245452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_ER_AAC_LC:
309345452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_ER_AAC_SCAL:
309445452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_ER_BSAC:
309545452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_ER_AAC_LD:
309645452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    extensionFlag = 1;
309745452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    break;
309845452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                default:
309945452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    TRESPASS();
310045452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    break;
310145452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                }
310245452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                ALOGW("csd missing extension flag; assuming %d for object type %u.",
310345452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                        extensionFlag, objectType);
310445452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            }
3105f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
310645452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            if (numChannels == 0) {
3107f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                int32_t channelsEffectiveNum = 0;
3108f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                int32_t channelsNum = 0;
3109b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                const int32_t ElementInstanceTag __unused = br.getBits(4);
3110b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                const int32_t Profile __unused = br.getBits(2);
3111b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                const int32_t SamplingFrequencyIndex __unused = br.getBits(4);
3112f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumFrontChannelElements = br.getBits(4);
3113f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumSideChannelElements = br.getBits(4);
3114f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumBackChannelElements = br.getBits(4);
3115f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumLfeChannelElements = br.getBits(2);
3116b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                const int32_t NumAssocDataElements __unused = br.getBits(3);
3117b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                const int32_t NumValidCcElements __unused = br.getBits(4);
3118f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3119f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t MonoMixdownPresent = br.getBits(1);
3120f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                if (MonoMixdownPresent != 0) {
3121b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t MonoMixdownElementNumber __unused = br.getBits(4);
3122f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
3123f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3124f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t StereoMixdownPresent = br.getBits(1);
3125f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                if (StereoMixdownPresent != 0) {
3126b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t StereoMixdownElementNumber __unused = br.getBits(4);
3127f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
3128f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3129f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t MatrixMixdownIndexPresent = br.getBits(1);
3130f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                if (MatrixMixdownIndexPresent != 0) {
3131b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t MatrixMixdownIndex __unused = br.getBits(2);
3132b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t PseudoSurroundEnable __unused = br.getBits(1);
3133f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
3134f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3135f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                int i;
3136f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumFrontChannelElements; i++) {
3137f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t FrontElementIsCpe = br.getBits(1);
3138b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t FrontElementTagSelect __unused = br.getBits(4);
3139f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += FrontElementIsCpe ? 2 : 1;
3140f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
3141f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3142f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumSideChannelElements; i++) {
3143f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t SideElementIsCpe = br.getBits(1);
3144b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t SideElementTagSelect __unused = br.getBits(4);
3145f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += SideElementIsCpe ? 2 : 1;
3146f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
3147f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3148f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumBackChannelElements; i++) {
3149f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t BackElementIsCpe = br.getBits(1);
3150b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t BackElementTagSelect __unused = br.getBits(4);
3151f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += BackElementIsCpe ? 2 : 1;
3152f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
3153f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                channelsEffectiveNum = channelsNum;
3154f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3155f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumLfeChannelElements; i++) {
3156b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t LfeElementTagSelect __unused = br.getBits(4);
3157f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += 1;
3158f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
3159f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                ALOGV("mpeg4 audio channelsNum = %d", channelsNum);
3160f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                ALOGV("mpeg4 audio channelsEffectiveNum = %d", channelsEffectiveNum);
3161f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                numChannels = channelsNum;
3162f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            }
3163f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        }
3164f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    }
3165f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3166ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (numChannels == 0) {
3167ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_UNSUPPORTED;
3168ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
3169ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3170f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake    if (mLastTrack == NULL)
3171f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake        return ERROR_MALFORMED;
3172f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
3173ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevSampleRate;
3174ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
3175ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3176ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevSampleRate != sampleRate) {
31773856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("mpeg4 audio sample rate different from previous setting. "
3178ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevSampleRate, sampleRate);
3179ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
3180ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3181ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
3182ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3183ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevChannelCount;
3184ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
3185ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3186ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevChannelCount != numChannels) {
31873856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("mpeg4 audio channel count different from previous setting. "
3188ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevChannelCount, numChannels);
3189ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
3190ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3191ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
3192ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3193ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    return OK;
3194ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber}
3195ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
319620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
319720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
319820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::MPEG4Source(
3199942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen        const sp<MPEG4Extractor> &owner,
320020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        const sp<MetaData> &format,
3201693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &dataSource,
320248c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        int32_t timeScale,
320305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const sp<SampleTable> &sampleTable,
320405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        Vector<SidxEntry> &sidx,
3205c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        const Trex *trex,
320605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t firstMoofOffset)
3207942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    : mOwner(owner),
3208942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen      mFormat(format),
320920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDataSource(dataSource),
321048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber      mTimescale(timeScale),
321120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSampleTable(sampleTable),
321220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCurrentSampleIndex(0),
321305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentFragmentIndex(0),
321405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mSegments(sidx),
3215c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen      mTrex(trex),
321605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mFirstMoofOffset(firstMoofOffset),
321705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentMoofOffset(firstMoofOffset),
321805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentTime(0),
3219ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoAllocSize(0),
3220ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoSizes(NULL),
3221ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoOffsetsAllocSize(0),
3222ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoOffsets(NULL),
322320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mIsAVC(false),
32243b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar      mIsHEVC(false),
32256064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber      mNALLengthSize(0),
322620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mStarted(false),
322720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mGroup(NULL),
322820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mBuffer(NULL),
3229dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber      mWantsNALFragments(false),
32300024245e134467d120b40099da16c467dc365e76Andreas Huber      mSrcBuffer(NULL) {
3231ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3232c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    memset(&mTrackFragmentHeaderInfo, 0, sizeof(mTrackFragmentHeaderInfo));
3233c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
3234ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mFormat->findInt32(kKeyCryptoMode, &mCryptoMode);
323548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    mDefaultIVSize = 0;
3236ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mFormat->findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize);
3237ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t keytype;
3238ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    const void *key;
3239ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    size_t keysize;
3240ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mFormat->findData(kKeyCryptoKey, &keytype, &key, &keysize)) {
3241ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        CHECK(keysize <= 16);
3242ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memset(mCryptoKey, 0, 16);
3243ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memcpy(mCryptoKey, key, keysize);
3244ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3245ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
324620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
324720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mFormat->findCString(kKeyMIMEType, &mime);
3248dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(success);
324920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
325018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber    mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
32513b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    mIsHEVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC);
32526064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
32536064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    if (mIsAVC) {
32546064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        uint32_t type;
32556064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const void *data;
32566064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t size;
32576064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(format->findData(kKeyAVCC, &type, &data, &size));
32586064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
32596064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const uint8_t *ptr = (const uint8_t *)data;
32606064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
32616064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(size >= 7);
3262ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
32636064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
32646064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        // The number of bytes used to encode the length of a NAL unit.
32656064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        mNALLengthSize = 1 + (ptr[4] & 3);
32663b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    } else if (mIsHEVC) {
32673b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        uint32_t type;
32683b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        const void *data;
32693b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        size_t size;
32703b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        CHECK(format->findData(kKeyHVCC, &type, &data, &size));
32713b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
32723b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        const uint8_t *ptr = (const uint8_t *)data;
32733b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
32743b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        CHECK(size >= 7);
32753b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
32763b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
32773b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        mNALLengthSize = 1 + (ptr[14 + 7] & 3);
32786064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
327905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
328005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    CHECK(format->findInt32(kKeyTrackID, &mTrackId));
328105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
328205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mFirstMoofOffset != 0) {
328305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t offset = mFirstMoofOffset;
328405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        parseChunk(&offset);
328505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
328620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
328720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
328820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::~MPEG4Source() {
328920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mStarted) {
329020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        stop();
329120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
3292ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    free(mCurrentSampleInfoSizes);
3293ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    free(mCurrentSampleInfoOffsets);
329420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
329520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
329620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::start(MetaData *params) {
32977b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
32987b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
3299dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(!mStarted);
330020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
330120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t val;
3302dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (params && params->findInt32(kKeyWantsNALFragments, &val)
330320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        && val != 0) {
3304dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = true;
330520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    } else {
3306dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = false;
330720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
330820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3309afd492436efc7f66b958da14659b52232efa5910Marco Nelissen    int32_t tmp;
3310afd492436efc7f66b958da14659b52232efa5910Marco Nelissen    CHECK(mFormat->findInt32(kKeyMaxInputSize, &tmp));
3311afd492436efc7f66b958da14659b52232efa5910Marco Nelissen    size_t max_size = tmp;
331220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3313afd492436efc7f66b958da14659b52232efa5910Marco Nelissen    // A somewhat arbitrary limit that should be sufficient for 8k video frames
3314afd492436efc7f66b958da14659b52232efa5910Marco Nelissen    // If you see the message below for a valid input stream: increase the limit
3315afd492436efc7f66b958da14659b52232efa5910Marco Nelissen    if (max_size > 64 * 1024 * 1024) {
3316afd492436efc7f66b958da14659b52232efa5910Marco Nelissen        ALOGE("bogus max input size: %zu", max_size);
3317afd492436efc7f66b958da14659b52232efa5910Marco Nelissen        return ERROR_MALFORMED;
3318afd492436efc7f66b958da14659b52232efa5910Marco Nelissen    }
3319afd492436efc7f66b958da14659b52232efa5910Marco Nelissen    mGroup = new MediaBufferGroup;
3320738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    mGroup->add_buffer(new MediaBuffer(max_size));
33210024245e134467d120b40099da16c467dc365e76Andreas Huber
33228da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    mSrcBuffer = new (std::nothrow) uint8_t[max_size];
33238da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    if (mSrcBuffer == NULL) {
33248da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        // file probably specified a bad max size
3325afd492436efc7f66b958da14659b52232efa5910Marco Nelissen        delete mGroup;
3326afd492436efc7f66b958da14659b52232efa5910Marco Nelissen        mGroup = NULL;
33278da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        return ERROR_MALFORMED;
33288da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    }
332920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
333020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = true;
333120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
333220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
333320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
333420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
333520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::stop() {
33367b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
33377b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
3338dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
333920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
334020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mBuffer != NULL) {
334120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->release();
334220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
334320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
334420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33450024245e134467d120b40099da16c467dc365e76Andreas Huber    delete[] mSrcBuffer;
33460024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = NULL;
33470024245e134467d120b40099da16c467dc365e76Andreas Huber
334820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    delete mGroup;
334920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = NULL;
335020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
335120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = false;
335220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mCurrentSampleIndex = 0;
335320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
335420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
335520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
335620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
335705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseChunk(off64_t *offset) {
335805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t hdr[2];
335905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
336005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_IO;
336105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
336205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t chunk_size = ntohl(hdr[0]);
336305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t chunk_type = ntohl(hdr[1]);
336405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t data_offset = *offset + 8;
336505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
336605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (chunk_size == 1) {
336705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
336805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_IO;
336905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
337005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        chunk_size = ntoh64(chunk_size);
337105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        data_offset += 8;
337205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
337305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (chunk_size < 16) {
337405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            // The smallest valid chunk is 16 bytes long in this case.
337505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
337605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
337705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (chunk_size < 8) {
337805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // The smallest valid chunk is 8 bytes long.
337905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
338005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
338105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
338205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    char chunk[5];
338305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    MakeFourCCString(chunk_type, chunk);
3384ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar    ALOGV("MPEG4Source chunk %s @ %#llx", chunk, (long long)*offset);
338505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
338605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t chunk_data_size = *offset + chunk_size - data_offset;
338705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
338805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    switch(chunk_type) {
338905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
339005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'r', 'a', 'f'):
339105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('m', 'o', 'o', 'f'): {
339205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t stop_offset = *offset + chunk_size;
339305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset = data_offset;
339405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            while (*offset < stop_offset) {
339505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err = parseChunk(offset);
339605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (err != OK) {
339705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return err;
339805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
339905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
340005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
34013f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                // *offset points to the box following this moof. Find the next moof from there.
34023f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen
34033f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                while (true) {
34043f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
34053f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                        return ERROR_END_OF_STREAM;
34063f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    }
34073f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    chunk_size = ntohl(hdr[0]);
34083f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    chunk_type = ntohl(hdr[1]);
34093f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
34103f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                        mNextMoofOffset = *offset;
34113f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                        break;
34123f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    }
34133f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    *offset += chunk_size;
34143f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                }
341505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
341605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
341705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
341805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
341905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'f', 'h', 'd'): {
342005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err;
342105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if ((err = parseTrackFragmentHeader(data_offset, chunk_data_size)) != OK) {
342205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return err;
342305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
342405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                *offset += chunk_size;
342505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                break;
342605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
342705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
342805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'r', 'u', 'n'): {
342905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err;
343005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (mLastParsedTrackId == mTrackId) {
343105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    if ((err = parseTrackFragmentRun(data_offset, chunk_data_size)) != OK) {
343205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        return err;
343305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    }
343405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
343505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
343605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                *offset += chunk_size;
343705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                break;
343805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
343905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3440ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'a', 'i', 'z'): {
3441ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            status_t err;
3442ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((err = parseSampleAuxiliaryInformationSizes(data_offset, chunk_data_size)) != OK) {
3443ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return err;
3444ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3445ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
3446ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
3447ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3448ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'a', 'i', 'o'): {
3449ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            status_t err;
3450ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((err = parseSampleAuxiliaryInformationOffsets(data_offset, chunk_data_size)) != OK) {
3451ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return err;
3452ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3453ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
3454ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
3455ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3456ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3457ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('m', 'd', 'a', 't'): {
3458ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // parse DRM info if present
3459ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("MPEG4Source::parseChunk mdat");
3460ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // if saiz/saoi was previously observed, do something with the sampleinfos
3461ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
3462ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
3463ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3464ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
346505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        default: {
346605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset += chunk_size;
346705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
346805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
346905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
347005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
347105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
347205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
347384333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG4Source::parseSampleAuxiliaryInformationSizes(
347484333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        off64_t offset, off64_t /* size */) {
3475ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("parseSampleAuxiliaryInformationSizes");
3476ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // 14496-12 8.7.12
3477ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t version;
3478ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(
3479ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset, &version, sizeof(version))
3480ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            < (ssize_t)sizeof(version)) {
3481ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3482ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3483ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3484ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (version != 0) {
3485ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_UNSUPPORTED;
3486ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3487ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
3488ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3489ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t flags;
3490ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt24(offset, &flags)) {
3491ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3492ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3493ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 3;
3494ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3495ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (flags & 1) {
3496ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        uint32_t tmp;
3497ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
3498ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_MALFORMED;
3499ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3500ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentAuxInfoType = tmp;
3501ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        offset += 4;
3502ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
3503ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_MALFORMED;
3504ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3505ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentAuxInfoTypeParameter = tmp;
3506ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        offset += 4;
3507ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3508ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3509ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t defsize;
3510ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(offset, &defsize, 1) != 1) {
3511ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_MALFORMED;
3512ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3513ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mCurrentDefaultSampleInfoSize = defsize;
3514ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
3515ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3516ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t smplcnt;
3517ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &smplcnt)) {
3518ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_MALFORMED;
3519ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
352048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    mCurrentSampleInfoCount = smplcnt;
3521ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 4;
3522ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
352348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (mCurrentDefaultSampleInfoSize != 0) {
352448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        ALOGV("@@@@ using default sample info size of %d", mCurrentDefaultSampleInfoSize);
352548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return OK;
352648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
3527ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (smplcnt > mCurrentSampleInfoAllocSize) {
3528ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoSizes = (uint8_t*) realloc(mCurrentSampleInfoSizes, smplcnt);
3529ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoAllocSize = smplcnt;
3530ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3531ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3532ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mDataSource->readAt(offset, mCurrentSampleInfoSizes, smplcnt);
3533ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    return OK;
3534ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen}
3535ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
353684333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(
353784333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        off64_t offset, off64_t /* size */) {
3538ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("parseSampleAuxiliaryInformationOffsets");
3539ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // 14496-12 8.7.13
3540ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t version;
3541ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(offset, &version, sizeof(version)) != 1) {
3542ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3543ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3544ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
3545ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3546ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t flags;
3547ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt24(offset, &flags)) {
3548ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3549ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3550ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 3;
3551ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3552ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t entrycount;
3553ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &entrycount)) {
3554ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3555ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3556ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 4;
3557ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3558ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (entrycount > mCurrentSampleInfoOffsetsAllocSize) {
3559ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoOffsets = (uint64_t*) realloc(mCurrentSampleInfoOffsets, entrycount * 8);
3560ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoOffsetsAllocSize = entrycount;
3561ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3562ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mCurrentSampleInfoOffsetCount = entrycount;
3563ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3564ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < entrycount; i++) {
3565ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (version == 0) {
3566ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t tmp;
3567ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (!mDataSource->getUInt32(offset, &tmp)) {
3568ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
3569ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3570ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mCurrentSampleInfoOffsets[i] = tmp;
3571ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset += 4;
3572ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        } else {
3573ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint64_t tmp;
3574ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (!mDataSource->getUInt64(offset, &tmp)) {
3575ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
3576ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3577ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mCurrentSampleInfoOffsets[i] = tmp;
3578ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset += 8;
3579ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3580ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3581ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3582ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // parse clear/encrypted data
3583ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3584ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    off64_t drmoffset = mCurrentSampleInfoOffsets[0]; // from moof
3585ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3586ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    drmoffset += mCurrentMoofOffset;
3587ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int ivlength;
3588ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    CHECK(mFormat->findInt32(kKeyCryptoDefaultIVSize, &ivlength));
358948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
359048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    // read CencSampleAuxiliaryDataFormats
3591ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mCurrentSampleInfoCount; i++) {
3592ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Sample *smpl = &mCurrentSamples.editItemAt(i);
3593ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3594ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memset(smpl->iv, 0, 16);
3595ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (mDataSource->readAt(drmoffset, smpl->iv, ivlength) != ivlength) {
3596ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_IO;
3597ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3598ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3599ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        drmoffset += ivlength;
3600ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
360148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        int32_t smplinfosize = mCurrentDefaultSampleInfoSize;
360248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        if (smplinfosize == 0) {
360348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smplinfosize = mCurrentSampleInfoSizes[i];
3604ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
360548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        if (smplinfosize > ivlength) {
360648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint16_t numsubsamples;
360748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (!mDataSource->getUInt16(drmoffset, &numsubsamples)) {
3608ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
3609ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3610ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            drmoffset += 2;
361148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            for (size_t j = 0; j < numsubsamples; j++) {
361248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                uint16_t numclear;
361348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                uint32_t numencrypted;
361448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                if (!mDataSource->getUInt16(drmoffset, &numclear)) {
361548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                    return ERROR_IO;
361648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                }
361748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                drmoffset += 2;
361848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                if (!mDataSource->getUInt32(drmoffset, &numencrypted)) {
361948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                    return ERROR_IO;
362048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                }
362148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                drmoffset += 4;
362248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->clearsizes.add(numclear);
362348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->encryptedsizes.add(numencrypted);
3624ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
362548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        } else {
362648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smpl->clearsizes.add(0);
362748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smpl->encryptedsizes.add(smpl->size);
3628ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3629ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3630ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3631ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3632ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    return OK;
3633ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen}
3634ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
363505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentHeader(off64_t offset, off64_t size) {
363605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
363705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 8) {
363805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
363905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
364005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
364105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
3642ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags
364305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
364405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
364505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
364605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & 0xff000000) {
364705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
364805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
364905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
365005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, (uint32_t*)&mLastParsedTrackId)) {
365105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
365205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
365305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
365405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mLastParsedTrackId != mTrackId) {
365505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // this is not the right track, skip it
365605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
365705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
365805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
365905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mFlags = flags;
366005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mTrackID = mLastParsedTrackId;
366105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 8;
366205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 8;
366305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
366405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("fragment header: %08x %08x", flags, mTrackFragmentHeaderInfo.mTrackID);
366505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
366605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent) {
366705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 8) {
366805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
366905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
367005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
367105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset, &mTrackFragmentHeaderInfo.mBaseDataOffset)) {
367205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
367305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
367405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 8;
367505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 8;
367605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
367705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
367805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent) {
367905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
368005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
368105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
368205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
368305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mSampleDescriptionIndex)) {
368405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
368505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
368605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
368705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
368805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
368905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
369005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
369105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
369205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
369305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
369405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
369505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleDuration)) {
369605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
369705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
369805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
369905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
370005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
370105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
370205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
370305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
370405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
370505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
370605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
370705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleSize)) {
370805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
370905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
371005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
371105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
371205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
371305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
371405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
371505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
371605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
371705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
371805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
371905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleFlags)) {
372005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
372105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
372205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
372305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
372405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
372505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
372605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!(flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent)) {
372705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mTrackFragmentHeaderInfo.mBaseDataOffset = mCurrentMoofOffset;
372805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
372905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
373005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mDataOffset = 0;
373105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
373205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
373305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
373405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentRun(off64_t offset, off64_t size) {
373505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
373605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Extractor::parseTrackFragmentRun");
373705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 8) {
373805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
373905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
374005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
374105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    enum {
374205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kDataOffsetPresent                  = 0x01,
374305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kFirstSampleFlagsPresent            = 0x04,
374405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleDurationPresent              = 0x100,
374505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleSizePresent                  = 0x200,
374605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleFlagsPresent                 = 0x400,
374705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleCompositionTimeOffsetPresent = 0x800,
374805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
374905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
375005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
375105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) {
375205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
375305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
375405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("fragment run flags: %08x", flags);
375505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
375605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & 0xff000000) {
375705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
375805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
375905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
376005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if ((flags & kFirstSampleFlagsPresent) && (flags & kSampleFlagsPresent)) {
376105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // These two shall not be used together.
376205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
376305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
376405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
376505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t sampleCount;
376605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, &sampleCount)) {
376705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
376805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
376905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 8;
377005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 8;
377105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
377205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t dataOffset = mTrackFragmentHeaderInfo.mDataOffset;
377305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
377405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t firstSampleFlags = 0;
377505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
377605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kDataOffsetPresent) {
377705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
377805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
377905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
378005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
378105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int32_t dataOffsetDelta;
378205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, (uint32_t*)&dataOffsetDelta)) {
378305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
378405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
378505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
378605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        dataOffset = mTrackFragmentHeaderInfo.mBaseDataOffset + dataOffsetDelta;
378705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
378805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
378905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
379005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
379105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
379205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kFirstSampleFlagsPresent) {
379305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
379405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
379505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
379605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
379705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &firstSampleFlags)) {
379805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
379905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
380005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
380105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
380205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
380305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
380405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t sampleDuration = 0, sampleSize = 0, sampleFlags = 0,
380505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen             sampleCtsOffset = 0;
380605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
380705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size_t bytesPerSample = 0;
380805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleDurationPresent) {
380905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
381005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
381105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
381205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration;
3813c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    } else if (mTrex) {
3814c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        sampleDuration = mTrex->default_sample_duration;
381505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
381605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
381705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleSizePresent) {
381805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
381905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
382005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
382105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
382205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
382305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
382405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
382505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
382605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleFlagsPresent) {
382705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
382805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
382905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
383005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
383105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
383205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
383305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
383405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
383505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleCompositionTimeOffsetPresent) {
383605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
383705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
383805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleCtsOffset = 0;
383905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
384005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3841ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar    if (size < (off64_t)(sampleCount * bytesPerSample)) {
384205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
384305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
384405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
384505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Sample tmp;
384605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    for (uint32_t i = 0; i < sampleCount; ++i) {
384705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleDurationPresent) {
384805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleDuration)) {
384905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
385005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
385105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
385205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
385305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
385405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleSizePresent) {
385505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleSize)) {
385605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
385705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
385805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
385905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
386005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
386105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleFlagsPresent) {
386205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleFlags)) {
386305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
386405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
386505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
386605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
386705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
386805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleCompositionTimeOffsetPresent) {
386905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleCtsOffset)) {
387005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
387105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
387205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
387305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
387405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3875a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("adding sample %d at offset 0x%08" PRIx64 ", size %u, duration %u, "
3876ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen              " flags 0x%08x", i + 1,
387705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dataOffset, sampleSize, sampleDuration,
387805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                (flags & kFirstSampleFlagsPresent) && i == 0
387905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ? firstSampleFlags : sampleFlags);
388005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.offset = dataOffset;
388105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.size = sampleSize;
388205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.duration = sampleDuration;
3883c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        tmp.compositionOffset = sampleCtsOffset;
388405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentSamples.add(tmp);
388505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
388605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        dataOffset += sampleSize;
388705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
388805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
388905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mDataOffset = dataOffset;
389005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
389105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
389205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
389305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
389420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> MPEG4Source::getFormat() {
38957b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
38967b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
389720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return mFormat;
389820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
389920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
39006064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const {
39016064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    switch (mNALLengthSize) {
39026064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 1:
39036064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return *data;
39046064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 2:
39056064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U16_AT(data);
39066064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 3:
39076064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return ((size_t)data[0] << 16) | U16_AT(&data[1]);
39086064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 4:
39096064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U32_AT(data);
39106064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
39116064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
39126064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // This cannot happen, mNALLengthSize springs to life by adding 1 to
39136064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // a 2-bit integer.
39146064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    CHECK(!"Should not be here.");
39156064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
39166064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    return 0;
39176064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber}
39186064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
391920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::read(
392020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
39217b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
39227b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
3923dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
392420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
392505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mFirstMoofOffset > 0) {
392605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return fragmentedRead(out, options);
392705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
392805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
392920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *out = NULL;
393020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3931abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    int64_t targetSampleTimeUs = -1;
3932abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
393320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t seekTimeUs;
3934abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
3935abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
3936abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t findFlags = 0;
3937abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        switch (mode) {
3938abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_PREVIOUS_SYNC:
3939abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagBefore;
3940abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3941abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_NEXT_SYNC:
3942abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagAfter;
3943abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3944abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST_SYNC:
3945abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST:
3946abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagClosest;
3947abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3948abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            default:
3949abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                CHECK(!"Should not be here.");
3950abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3951abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3952abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
395320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        uint32_t sampleIndex;
3954abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        status_t err = mSampleTable->findSampleAtTime(
3955599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar                seekTimeUs, 1000000, mTimescale,
3956abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                &sampleIndex, findFlags);
3957abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3958abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
3959abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // We found the closest sample already, now we want the sync
3960abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // sample preceding it (or the sample itself of course), even
3961abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // if the subsequent sync sample is closer.
3962abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            findFlags = SampleTable::kFlagBefore;
3963abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3964abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3965abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleIndex;
3966abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (err == OK) {
3967abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            err = mSampleTable->findSyncSampleNear(
3968abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    sampleIndex, &syncSampleIndex, findFlags);
3969abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
397020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3971788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        uint32_t sampleTime;
3972788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        if (err == OK) {
3973788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber            err = mSampleTable->getMetaDataForSample(
3974788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber                    sampleIndex, NULL, NULL, &sampleTime);
3975788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        }
3976788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber
397720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (err != OK) {
39785295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            if (err == ERROR_OUT_OF_RANGE) {
39795295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // An attempt to seek past the end of the stream would
39805295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // normally cause this ERROR_OUT_OF_RANGE error. Propagating
39815295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // this all the way to the MediaPlayer would cause abnormal
39825295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // termination. Legacy behaviour appears to be to behave as if
39835295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // we had seeked to the end of stream, ending normally.
39845295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                err = ERROR_END_OF_STREAM;
39855295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            }
398605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("end of stream");
398720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return err;
398820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
398920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3990abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
3991abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
3992abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3993abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3994abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#if 0
3995abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleTime;
3996abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
3997abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    syncSampleIndex, NULL, NULL, &syncSampleTime));
3998abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3999df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("seek to time %lld us => sample at time %lld us, "
4000abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             "sync sample at time %lld us",
4001abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             seekTimeUs,
4002abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             sampleTime * 1000000ll / mTimescale,
4003abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             syncSampleTime * 1000000ll / mTimescale);
4004abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#endif
4005abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
4006abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        mCurrentSampleIndex = syncSampleIndex;
400720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mBuffer != NULL) {
400820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
400920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
401020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
401120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
401220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // fall through
401320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
401420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4015c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset;
40160024245e134467d120b40099da16c467dc365e76Andreas Huber    size_t size;
4017170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih    uint32_t cts, stts;
40188bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    bool isSyncSample;
4019dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool newBuffer = false;
4020dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (mBuffer == NULL) {
4021dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        newBuffer = true;
402220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4023c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        status_t err =
4024c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber            mSampleTable->getMetaDataForSample(
4025170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                    mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample, &stts);
402620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4027dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
4028dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
4029dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
4030dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4031dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        err = mGroup->acquire_buffer(&mBuffer);
4032c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
4033dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
4034ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            CHECK(mBuffer == NULL);
4035dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
4036dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
4037c1a104aaad2d84a57bf5d87dd030d2bef56bf541Marco Nelissen        if (size > mBuffer->size()) {
4038c1a104aaad2d84a57bf5d87dd030d2bef56bf541Marco Nelissen            ALOGE("buffer too small: %zu > %zu", size, mBuffer->size());
4039c1a104aaad2d84a57bf5d87dd030d2bef56bf541Marco Nelissen            return ERROR_BUFFER_TOO_SMALL;
4040c1a104aaad2d84a57bf5d87dd030d2bef56bf541Marco Nelissen        }
40410024245e134467d120b40099da16c467dc365e76Andreas Huber    }
404220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
40433b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    if ((!mIsAVC && !mIsHEVC) || mWantsNALFragments) {
4044dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (newBuffer) {
4045dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ssize_t num_bytes_read =
404634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
4047dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4048dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            if (num_bytes_read < (ssize_t)size) {
4049dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer->release();
4050dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer = NULL;
4051dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4052dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                return ERROR_IO;
4053dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            }
4054dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
40557b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber            CHECK(mBuffer != NULL);
4056dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->set_range(0, size);
4057dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->meta_data()->clear();
405848c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mBuffer->meta_data()->setInt64(
40594678a6dc5f09008481524949a9667af5a6190374Andreas Huber                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
4060170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih            mBuffer->meta_data()->setInt64(
4061170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                    kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
4062abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
4063abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            if (targetSampleTimeUs >= 0) {
4064abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                mBuffer->meta_data()->setInt64(
4065abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                        kKeyTargetTime, targetSampleTimeUs);
4066abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            }
4067abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
40688bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            if (isSyncSample) {
40698bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
40708bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            }
40718bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
4072dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ++mCurrentSampleIndex;
4073dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
4074dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
40753b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        if (!mIsAVC && !mIsHEVC) {
4076dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            *out = mBuffer;
4077dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
4078dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4079dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return OK;
4080dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
4081dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4082dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Each NAL unit is split up into its constituent fragments and
4083dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // each one of them returned in its own buffer.
4084dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
40856064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(mBuffer->range_length() >= mNALLengthSize);
4086dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4087dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        const uint8_t *src =
4088dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
4089dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
40906064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t nal_size = parseNALSize(src);
4091e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
409229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("incomplete NAL unit.");
4093e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
4094e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer->release();
4095e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer = NULL;
4096e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
4097e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            return ERROR_MALFORMED;
4098e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        }
4099dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4100dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        MediaBuffer *clone = mBuffer->clone();
41017b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(clone != NULL);
41026064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
4103dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
41047b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(mBuffer != NULL);
4105dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mBuffer->set_range(
41066064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_offset() + mNALLengthSize + nal_size,
41076064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_length() - mNALLengthSize - nal_size);
4108dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4109dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (mBuffer->range_length() == 0) {
4110dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->release();
4111dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
4112dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
4113dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4114dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        *out = clone;
4115dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4116dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        return OK;
4117dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    } else {
4118dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Whole NAL units are returned but each fragment is prefixed by
4119dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // the start code (0x00 00 00 01).
4120dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        ssize_t num_bytes_read = 0;
4121dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        int32_t drm = 0;
4122dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
4123dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (usesDRM) {
4124dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            num_bytes_read =
4125dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
4126dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
4127dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
4128dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
412920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
413020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (num_bytes_read < (ssize_t)size) {
413120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
413220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
413320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4134dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return ERROR_IO;
413520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
413620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4137dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (usesDRM) {
4138dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK(mBuffer != NULL);
4139dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            mBuffer->set_range(0, size);
41406064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
4141dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
4142dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            uint8_t *dstData = (uint8_t *)mBuffer->data();
4143dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size_t srcOffset = 0;
4144dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size_t dstOffset = 0;
4145e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
4146dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            while (srcOffset < size) {
4147bfed843041b6aaec13ee19996748a7a1476db9c8Lajos Molnar                bool isMalFormed = !isInRange((size_t)0u, size, srcOffset, mNALLengthSize);
414834fe252c89e33572d01fea981b58d7b115e76164James Dong                size_t nalLength = 0;
414934fe252c89e33572d01fea981b58d7b115e76164James Dong                if (!isMalFormed) {
415034fe252c89e33572d01fea981b58d7b115e76164James Dong                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
415134fe252c89e33572d01fea981b58d7b115e76164James Dong                    srcOffset += mNALLengthSize;
4152bfed843041b6aaec13ee19996748a7a1476db9c8Lajos Molnar                    isMalFormed = !isInRange((size_t)0u, size, srcOffset, nalLength);
415334fe252c89e33572d01fea981b58d7b115e76164James Dong                }
4154e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
415534fe252c89e33572d01fea981b58d7b115e76164James Dong                if (isMalFormed) {
415629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                    ALOGE("Video is malformed");
4157dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    mBuffer->release();
4158dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    mBuffer = NULL;
4159dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return ERROR_MALFORMED;
4160dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
4161dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
4162dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                if (nalLength == 0) {
4163dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    continue;
4164dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
4165dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4166dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                CHECK(dstOffset + 4 <= mBuffer->size());
4167dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4168dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
4169dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
4170dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
4171dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 1;
4172dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
4173dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                srcOffset += nalLength;
4174dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstOffset += nalLength;
4175dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
4176dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK_EQ(srcOffset, size);
4177dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK(mBuffer != NULL);
4178dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            mBuffer->set_range(0, dstOffset);
4179dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
4180dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
418120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->meta_data()->clear();
418248c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        mBuffer->meta_data()->setInt64(
41834678a6dc5f09008481524949a9667af5a6190374Andreas Huber                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
4184170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih        mBuffer->meta_data()->setInt64(
4185170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
4186abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
4187abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (targetSampleTimeUs >= 0) {
4188abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            mBuffer->meta_data()->setInt64(
4189abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    kKeyTargetTime, targetSampleTimeUs);
4190abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
4191abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
41928bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        if (isSyncSample) {
41938bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
41948bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        }
41958bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
419620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        ++mCurrentSampleIndex;
419720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
419820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        *out = mBuffer;
419920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
420020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
420120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
420220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
420320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
420420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
420505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::fragmentedRead(
420605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MediaBuffer **out, const ReadOptions *options) {
420705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
420805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Source::fragmentedRead");
420905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
421005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    CHECK(mStarted);
421105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
421205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    *out = NULL;
421305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
421405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t targetSampleTimeUs = -1;
421505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
421605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t seekTimeUs;
421705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ReadOptions::SeekMode mode;
421805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
421905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
422005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int numSidxEntries = mSegments.size();
422105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (numSidxEntries != 0) {
422205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            int64_t totalTime = 0;
422305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t totalOffset = mFirstMoofOffset;
422405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            for (int i = 0; i < numSidxEntries; i++) {
422505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                const SidxEntry *se = &mSegments[i];
422605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (totalTime + se->mDurationUs > seekTimeUs) {
422705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    // The requested time is somewhere in this segment
42283f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    if ((mode == ReadOptions::SEEK_NEXT_SYNC && seekTimeUs > totalTime) ||
422905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        (mode == ReadOptions::SEEK_CLOSEST_SYNC &&
423005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        (seekTimeUs - totalTime) > (totalTime + se->mDurationUs - seekTimeUs))) {
423105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        // requested next sync, or closest sync and it was closer to the end of
423205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        // this segment
423305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        totalTime += se->mDurationUs;
423405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        totalOffset += se->mSize;
423505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    }
423605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    break;
423705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
423805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                totalTime += se->mDurationUs;
423905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                totalOffset += se->mSize;
424005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
4241ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentMoofOffset = totalOffset;
4242ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSamples.clear();
4243ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSampleIndex = 0;
4244ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            parseChunk(&totalOffset);
4245ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentTime = totalTime * mTimescale / 1000000ll;
4246ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen        } else {
4247ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            // without sidx boxes, we can only seek to 0
4248ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentMoofOffset = mFirstMoofOffset;
4249ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSamples.clear();
4250ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSampleIndex = 0;
4251ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            off64_t tmp = mCurrentMoofOffset;
4252ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            parseChunk(&tmp);
4253ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentTime = 0;
425405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
425505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
425605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer != NULL) {
425705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
425805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
425905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
426005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
426105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // fall through
426205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
426305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
426405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t offset = 0;
4265442cc6dc48f8188e097617f7f804c314a9dacd0eAndreas Huber    size_t size = 0;
426605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t cts = 0;
426705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    bool isSyncSample = false;
426805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    bool newBuffer = false;
426905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mBuffer == NULL) {
427005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        newBuffer = true;
427105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
427205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mCurrentSampleIndex >= mCurrentSamples.size()) {
42733f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            // move to next fragment if there is one
42743f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            if (mNextMoofOffset <= mCurrentMoofOffset) {
42753f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                return ERROR_END_OF_STREAM;
42763f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            }
4277ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            off64_t nextMoof = mNextMoofOffset;
427805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentMoofOffset = nextMoof;
427905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentSamples.clear();
428005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentSampleIndex = 0;
428105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            parseChunk(&nextMoof);
4282ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            if (mCurrentSampleIndex >= mCurrentSamples.size()) {
4283ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen                return ERROR_END_OF_STREAM;
4284ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            }
428505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
428605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
428705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
428805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset = smpl->offset;
428905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size = smpl->size;
4290c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        cts = mCurrentTime + smpl->compositionOffset;
429105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentTime += smpl->duration;
429205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        isSyncSample = (mCurrentSampleIndex == 0); // XXX
429305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
429405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        status_t err = mGroup->acquire_buffer(&mBuffer);
429505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
429605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (err != OK) {
429705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer == NULL);
429805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("acquire_buffer returned %d", err);
429905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return err;
430005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
4301c1a104aaad2d84a57bf5d87dd030d2bef56bf541Marco Nelissen        if (size > mBuffer->size()) {
4302c1a104aaad2d84a57bf5d87dd030d2bef56bf541Marco Nelissen            ALOGE("buffer too small: %zu > %zu", size, mBuffer->size());
4303c1a104aaad2d84a57bf5d87dd030d2bef56bf541Marco Nelissen            return ERROR_BUFFER_TOO_SMALL;
4304c1a104aaad2d84a57bf5d87dd030d2bef56bf541Marco Nelissen        }
430505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
430605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
430748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
430848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    const sp<MetaData> bufmeta = mBuffer->meta_data();
430948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    bufmeta->clear();
431048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (smpl->encryptedsizes.size()) {
431148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // store clear/encrypted lengths in metadata
431248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyPlainSizes, 0,
431348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->clearsizes.array(), smpl->clearsizes.size() * 4);
431448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyEncryptedSizes, 0,
431548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
431648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
431748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
431848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setInt32(kKeyCryptoMode, mCryptoMode);
431948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16);
432048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
432148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
43223b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    if ((!mIsAVC && !mIsHEVC)|| mWantsNALFragments) {
432305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (newBuffer) {
4324da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            if (!isInRange((size_t)0u, mBuffer->size(), size)) {
4325da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                mBuffer->release();
4326da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                mBuffer = NULL;
4327da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih
4328da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                ALOGE("fragmentedRead ERROR_MALFORMED size %zu", size);
4329da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                return ERROR_MALFORMED;
4330da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            }
4331da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih
433205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ssize_t num_bytes_read =
433305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
433405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
433505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (num_bytes_read < (ssize_t)size) {
433605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->release();
433705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer = NULL;
433805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
4339da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                ALOGE("i/o error");
434005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_IO;
434105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
434205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
434305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
434405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, size);
434505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt64(
434605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
4347170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih            mBuffer->meta_data()->setInt64(
4348170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                    kKeyDuration, ((int64_t)smpl->duration * 1000000) / mTimescale);
434905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
435005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (targetSampleTimeUs >= 0) {
435105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->meta_data()->setInt64(
435205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        kKeyTargetTime, targetSampleTimeUs);
435305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
435405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
435505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (isSyncSample) {
435605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
435705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
435805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
435905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ++mCurrentSampleIndex;
436005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
436105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
43623b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        if (!mIsAVC && !mIsHEVC) {
436305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *out = mBuffer;
436405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
436505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
436605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return OK;
436705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
436805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
436905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // Each NAL unit is split up into its constituent fragments and
437005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // each one of them returned in its own buffer.
437105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
437205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(mBuffer->range_length() >= mNALLengthSize);
437305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
437405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const uint8_t *src =
437505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
437605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
437705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size_t nal_size = parseNALSize(src);
437805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
437905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGE("incomplete NAL unit.");
438005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
438105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
438205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
438305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
438405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
438505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
438605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
438705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MediaBuffer *clone = mBuffer->clone();
438805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(clone != NULL);
438905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
439005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
439105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(mBuffer != NULL);
439205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer->set_range(
439305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->range_offset() + mNALLengthSize + nal_size,
439405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->range_length() - mNALLengthSize - nal_size);
439505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
439605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer->range_length() == 0) {
439705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
439805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
439905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
440005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
440105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        *out = clone;
440205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
440305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
440405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
440505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV("whole NAL");
440605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // Whole NAL units are returned but each fragment is prefixed by
440705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // the start code (0x00 00 00 01).
440805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ssize_t num_bytes_read = 0;
440905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int32_t drm = 0;
441005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
4411da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih        void *data = NULL;
4412da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih        bool isMalFormed = false;
441305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (usesDRM) {
4414da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            if (mBuffer == NULL || !isInRange((size_t)0u, mBuffer->size(), size)) {
4415da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                isMalFormed = true;
4416da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            } else {
4417da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                data = mBuffer->data();
4418da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            }
441905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else {
4420da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            int32_t max_size;
4421da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            if (mFormat == NULL
4422da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                    || !mFormat->findInt32(kKeyMaxInputSize, &max_size)
4423da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                    || !isInRange((size_t)0u, (size_t)max_size, size)) {
4424da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                isMalFormed = true;
4425da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            } else {
4426da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                data = mSrcBuffer;
4427da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            }
442805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
442905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
4430da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih        if (isMalFormed || data == NULL) {
4431da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            ALOGE("isMalFormed size %zu", size);
4432da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            if (mBuffer != NULL) {
4433da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                mBuffer->release();
4434da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                mBuffer = NULL;
4435da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            }
4436da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            return ERROR_MALFORMED;
4437da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih        }
4438da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih        num_bytes_read = mDataSource->readAt(offset, data, size);
4439da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih
444005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (num_bytes_read < (ssize_t)size) {
444105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
444205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
444305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
4444da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            ALOGE("i/o error");
444505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_IO;
444605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
444705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
444805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (usesDRM) {
444905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
445005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, size);
445105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
445205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else {
445305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            uint8_t *dstData = (uint8_t *)mBuffer->data();
445405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            size_t srcOffset = 0;
445505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            size_t dstOffset = 0;
445605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
445705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            while (srcOffset < size) {
4458da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                isMalFormed = !isInRange((size_t)0u, size, srcOffset, mNALLengthSize);
445905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                size_t nalLength = 0;
446005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (!isMalFormed) {
446105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
446205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    srcOffset += mNALLengthSize;
4463da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                    isMalFormed = !isInRange((size_t)0u, size, srcOffset, nalLength)
4464da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                            || !isInRange((size_t)0u, mBuffer->size(), dstOffset, (size_t)4u)
4465da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                            || !isInRange((size_t)0u, mBuffer->size(), dstOffset + 4, nalLength);
446605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
446705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
446805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (isMalFormed) {
4469da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                    ALOGE("Video is malformed; nalLength %zu", nalLength);
447005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    mBuffer->release();
447105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    mBuffer = NULL;
447205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return ERROR_MALFORMED;
447305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
447405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
447505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (nalLength == 0) {
447605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    continue;
447705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
447805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
447905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                CHECK(dstOffset + 4 <= mBuffer->size());
448005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
448105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
448205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
448305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
448405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 1;
448505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
448605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                srcOffset += nalLength;
448705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstOffset += nalLength;
448805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
448905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK_EQ(srcOffset, size);
449005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
449105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, dstOffset);
449205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
449305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
449405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer->meta_data()->setInt64(
449505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
4496170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih        mBuffer->meta_data()->setInt64(
4497170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                kKeyDuration, ((int64_t)smpl->duration * 1000000) / mTimescale);
449805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
449905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (targetSampleTimeUs >= 0) {
450005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt64(
450105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    kKeyTargetTime, targetSampleTimeUs);
450205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
450305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
450405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (isSyncSample) {
450505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
450605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
450705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
450805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ++mCurrentSampleIndex;
450905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
451005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        *out = mBuffer;
451105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer = NULL;
451205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
451305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
451405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
451505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
451605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
4517bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas HuberMPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix(
4518bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        const char *mimePrefix) {
4519bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    for (Track *track = mFirstTrack; track != NULL; track = track->next) {
4520bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        const char *mime;
4521bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        if (track->meta != NULL
4522bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                && track->meta->findCString(kKeyMIMEType, &mime)
4523bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) {
4524bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber            return track;
4525bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        }
4526bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    }
4527bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber
4528bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    return NULL;
4529bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber}
4530bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber
45311b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool LegacySniffMPEG4(
4532693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
453320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[8];
453420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
453534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    ssize_t n = source->readAt(4, header, sizeof(header));
453620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (n < (ssize_t)sizeof(header)) {
453720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return false;
453820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
453920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
454020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
4541b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8)
4542b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8)
45430dba73763a04d39faf999dcc5ef12af3c99535a7Andreas Huber        || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
4544ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
4545983b449a27b5fa91eca82ede5204b4341899be62Andreas Huber        || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
454618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
45475a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        *confidence = 0.4;
454820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
454920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return true;
455020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
455120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
455220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return false;
455320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
455420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
45551b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool isCompatibleBrand(uint32_t fourcc) {
45561b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    static const uint32_t kCompatibleBrands[] = {
45571b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', 'm'),
45581b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', '2'),
45591b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('a', 'v', 'c', '1'),
45603b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        FOURCC('h', 'v', 'c', '1'),
45613b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        FOURCC('h', 'e', 'v', '1'),
45621b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('3', 'g', 'p', '4'),
45631b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '1'),
45641b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '2'),
45654cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong
45664cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        // Won't promise that the following file types can be played.
45674cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        // Just give these file types a chance.
45684cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        FOURCC('q', 't', ' ', ' '),  // Apple's QuickTime
45694cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        FOURCC('M', 'S', 'N', 'V'),  // Sony's PSP
457058fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber
457158fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber        FOURCC('3', 'g', '2', 'a'),  // 3GPP2
457258fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber        FOURCC('3', 'g', '2', 'b'),
45731b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    };
45741b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
45751b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    for (size_t i = 0;
45761b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]);
45771b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         ++i) {
45781b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        if (kCompatibleBrands[i] == fourcc) {
45791b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            return true;
45801b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
45811b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
45821b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
45831b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
45841b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
45851b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
45861b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// Attempt to actually parse the 'ftyp' atom and determine if a suitable
45871b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// compatible brand is present.
4588a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// Also try to identify where this file's metadata ends
4589a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// (end of the 'moov' atom) and report it to the caller as part of
4590a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// the metadata.
45911b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool BetterSniffMPEG4(
4592a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
4593a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        sp<AMessage> *meta) {
4594a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    // We scan up to 128 bytes to identify this file as an MP4.
4595a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    static const off64_t kMaxScanOffset = 128ll;
45961b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4597a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    off64_t offset = 0ll;
4598a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    bool foundGoodFileType = false;
4599a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    off64_t moovAtomEndOffset = -1ll;
4600a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    bool done = false;
46011b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4602a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    while (!done && offset < kMaxScanOffset) {
4603a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint32_t hdr[2];
4604a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        if (source->readAt(offset, hdr, 8) < 8) {
4605a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            return false;
4606a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        }
4607a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4608a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint64_t chunkSize = ntohl(hdr[0]);
4609a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint32_t chunkType = ntohl(hdr[1]);
4610a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        off64_t chunkDataOffset = offset + 8;
4611a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4612a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        if (chunkSize == 1) {
4613a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            if (source->readAt(offset + 8, &chunkSize, 8) < 8) {
46141b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                return false;
46151b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
46161b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4617a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            chunkSize = ntoh64(chunkSize);
4618a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            chunkDataOffset += 8;
4619a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4620a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            if (chunkSize < 16) {
4621a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                // The smallest valid chunk is 16 bytes long in this case.
4622a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                return false;
4623a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            }
4624a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        } else if (chunkSize < 8) {
4625a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            // The smallest valid chunk is 8 bytes long.
4626a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            return false;
4627a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        }
4628a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4629a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        off64_t chunkDataSize = offset + chunkSize - chunkDataOffset;
4630a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
463105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        char chunkstring[5];
463205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MakeFourCCString(chunkType, chunkstring);
4633ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar        ALOGV("saw chunk type %s, size %" PRIu64 " @ %lld", chunkstring, chunkSize, (long long)offset);
4634a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        switch (chunkType) {
4635a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            case FOURCC('f', 't', 'y', 'p'):
4636a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            {
4637a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                if (chunkDataSize < 8) {
4638a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    return false;
4639a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
4640a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4641a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4;
4642a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
4643a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (i == 1) {
4644a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        // Skip this index, it refers to the minorVersion,
4645a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        // not a brand.
4646a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        continue;
4647a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
4648a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4649a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    uint32_t brand;
4650a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (source->readAt(
4651a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                                chunkDataOffset + 4 * i, &brand, 4) < 4) {
4652a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        return false;
4653a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
4654a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4655a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    brand = ntohl(brand);
4656a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4657a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (isCompatibleBrand(brand)) {
4658a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        foundGoodFileType = true;
4659a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        break;
4660a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
4661a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
4662a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4663a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                if (!foundGoodFileType) {
4664a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    return false;
4665a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
4666a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
46671b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                break;
46681b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
4669a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4670a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            case FOURCC('m', 'o', 'o', 'v'):
4671a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            {
4672a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                moovAtomEndOffset = offset + chunkSize;
4673a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4674a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                done = true;
4675a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                break;
4676a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            }
4677a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4678a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            default:
4679a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                break;
46801b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
4681a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4682a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        offset += chunkSize;
46831b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
46841b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4685a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (!foundGoodFileType) {
46861b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return false;
46871b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
46881b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
46891b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
46905a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber    *confidence = 0.4f;
46911b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4692a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (moovAtomEndOffset >= 0) {
4693a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        *meta = new AMessage;
4694a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        (*meta)->setInt64("meta-data-size", moovAtomEndOffset);
4695a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4696ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar        ALOGV("found metadata size: %lld", (long long)moovAtomEndOffset);
4697a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    }
4698a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
46991b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return true;
47001b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
47011b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
47021b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberbool SniffMPEG4(
47035a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
4704a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        sp<AMessage> *meta) {
4705a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (BetterSniffMPEG4(source, mimeType, confidence, meta)) {
47061b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
47071b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
47081b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
47091b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    if (LegacySniffMPEG4(source, mimeType, confidence)) {
47105ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Identified supported mpeg4 through LegacySniffMPEG4.");
47111b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
47121b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
47131b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
47141b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
47151b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
47161b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
471720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
4718