MPEG4Extractor.cpp revision dd2d81b49d22642b15ac6dcbc5ad59d0c6f5c227
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>
3758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar#include <media/stagefright/foundation/ColorUtils.h>
3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBufferGroup.h>
4018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/String8.h>
4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
45fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé#include <byteswap.h>
46328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé#include "include/ID3.h"
47fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
48937c6bedd4b6e5c6cb29a238eb459047dedd3486Wei Jia#ifndef UINT32_MAX
49937c6bedd4b6e5c6cb29a238eb459047dedd3486Wei Jia#define UINT32_MAX       (4294967295U)
50937c6bedd4b6e5c6cb29a238eb459047dedd3486Wei Jia#endif
51937c6bedd4b6e5c6cb29a238eb459047dedd3486Wei Jia
5220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Source : public MediaSource {
5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Caller retains ownership of both "dataSource" and "sampleTable".
57942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    MPEG4Source(const sp<MPEG4Extractor> &owner,
58942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen                const sp<MetaData> &format,
59693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber                const sp<DataSource> &dataSource,
6048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                int32_t timeScale,
6105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                const sp<SampleTable> &sampleTable,
6205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                Vector<SidxEntry> &sidx,
63c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                const Trex *trex,
6405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                off64_t firstMoofOffset);
6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t start(MetaData *params = NULL);
6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t stop();
6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual sp<MetaData> getFormat();
7020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL);
7205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    virtual status_t fragmentedRead(MediaBuffer **buffer, const ReadOptions *options = NULL);
7320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
74693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huberprotected:
75693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    virtual ~MPEG4Source();
76693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber
7720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
787b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex mLock;
797b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
80942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    // keep the MPEG4Extractor around, since we're referencing its data
81942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    sp<MPEG4Extractor> mOwner;
8220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mFormat;
83693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<DataSource> mDataSource;
8420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t mTimescale;
85693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<SampleTable> mSampleTable;
8620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t mCurrentSampleIndex;
8705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t mCurrentFragmentIndex;
8805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Vector<SidxEntry> &mSegments;
89c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    const Trex *mTrex;
9005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mFirstMoofOffset;
9105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mCurrentMoofOffset;
9205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mNextMoofOffset;
9305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t mCurrentTime;
9405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int32_t mLastParsedTrackId;
9505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int32_t mTrackId;
9620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
97ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int32_t mCryptoMode;    // passed in from extractor
98ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int32_t mDefaultIVSize; // passed in from extractor
99ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t mCryptoKey[16]; // passed in from extractor
100ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentAuxInfoType;
101ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentAuxInfoTypeParameter;
10248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    int32_t mCurrentDefaultSampleInfoSize;
103ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoCount;
104ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoAllocSize;
105ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t* mCurrentSampleInfoSizes;
106ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoOffsetCount;
107ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoOffsetsAllocSize;
108ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint64_t* mCurrentSampleInfoOffsets;
109ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
11020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mIsAVC;
1113b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    bool mIsHEVC;
1126064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    size_t mNALLengthSize;
1136064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
11420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mStarted;
11520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBufferGroup *mGroup;
11720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *mBuffer;
11920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
120dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool mWantsNALFragments;
12120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1220024245e134467d120b40099da16c467dc365e76Andreas Huber    uint8_t *mSrcBuffer;
1230024245e134467d120b40099da16c467dc365e76Andreas Huber
1246064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    size_t parseNALSize(const uint8_t *data) const;
12505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseChunk(off64_t *offset);
12605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseTrackFragmentHeader(off64_t offset, off64_t size);
12705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseTrackFragmentRun(off64_t offset, off64_t size);
128ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    status_t parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size);
129ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    status_t parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size);
13005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
13105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    struct TrackFragmentHeaderInfo {
13205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        enum Flags {
13305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kBaseDataOffsetPresent         = 0x01,
13405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kSampleDescriptionIndexPresent = 0x02,
13505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleDurationPresent  = 0x08,
13605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleSizePresent      = 0x10,
13705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleFlagsPresent     = 0x20,
13805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDurationIsEmpty               = 0x10000,
13905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        };
14005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
14105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mTrackID;
14205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mFlags;
14305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint64_t mBaseDataOffset;
14405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mSampleDescriptionIndex;
14505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleDuration;
14605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleSize;
14705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleFlags;
14805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
14905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint64_t mDataOffset;
15005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
15105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    TrackFragmentHeaderInfo mTrackFragmentHeaderInfo;
15205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
15305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    struct Sample {
15405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t offset;
15505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size_t size;
15605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t duration;
157c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        int32_t compositionOffset;
158ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        uint8_t iv[16];
159ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Vector<size_t> clearsizes;
160ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Vector<size_t> encryptedsizes;
16105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
16205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Vector<Sample> mCurrentSamples;
1636064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
16420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source(const MPEG4Source &);
16520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source &operator=(const MPEG4Source &);
16620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
16720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
16850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This custom data source wraps an existing one and satisfies requests
16950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// falling entirely within a cached range from the cache while forwarding
17050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// all remaining requests to the wrapped datasource.
17150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This is used to cache the full sampletable metadata for a single track,
17250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// possibly wrapping multiple times to cover all tracks, i.e.
17350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// Each MPEG4DataSource caches the sampletable metadata for a single track.
17450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstruct MPEG4DataSource : public DataSource {
17650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource(const sp<DataSource> &source);
17750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual status_t initCheck() const;
179c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
180c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    virtual status_t getSize(off64_t *size);
18150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual uint32_t flags();
18250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
183c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    status_t setCachedRange(off64_t offset, size_t size);
18450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprotected:
18650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual ~MPEG4DataSource();
18750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprivate:
18950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex mLock;
19050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    sp<DataSource> mSource;
192c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t mCachedOffset;
19350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    size_t mCachedSize;
19450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    uint8_t *mCache;
19550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    void clearCache();
19750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource(const MPEG4DataSource &);
19950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource &operator=(const MPEG4DataSource &);
20050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber};
20150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
20250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source)
20350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    : mSource(source),
20450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCachedOffset(0),
20550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCachedSize(0),
20650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCache(NULL) {
20750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
20850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
20950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::~MPEG4DataSource() {
21050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    clearCache();
21150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
21250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
21350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Hubervoid MPEG4DataSource::clearCache() {
21450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (mCache) {
21550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        free(mCache);
21650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        mCache = NULL;
21750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
21850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
21950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedOffset = 0;
22050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedSize = 0;
22150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
22250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
22350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstatus_t MPEG4DataSource::initCheck() const {
22450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->initCheck();
22550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
22650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
227c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongssize_t MPEG4DataSource::readAt(off64_t offset, void *data, size_t size) {
22850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex::Autolock autoLock(mLock);
22950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
230bfed843041b6aaec13ee19996748a7a1476db9c8Lajos Molnar    if (isInRange(mCachedOffset, mCachedSize, offset, size)) {
23150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        memcpy(data, &mCache[offset - mCachedOffset], size);
23250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return size;
23350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
23450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
23550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->readAt(offset, data, size);
23650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
23750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
238c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4DataSource::getSize(off64_t *size) {
23950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->getSize(size);
24050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
24150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
24250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberuint32_t MPEG4DataSource::flags() {
24350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->flags();
24450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
24550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
246c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4DataSource::setCachedRange(off64_t offset, size_t size) {
24750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex::Autolock autoLock(mLock);
24850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
24950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    clearCache();
25050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
25150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCache = (uint8_t *)malloc(size);
25250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
25350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (mCache == NULL) {
25450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return -ENOMEM;
25550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
25650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
25750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedOffset = offset;
25850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedSize = size;
25950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
26050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    ssize_t err = mSource->readAt(mCachedOffset, mCache, mCachedSize);
26150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
26250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (err < (ssize_t)size) {
26350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        clearCache();
26450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
26550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return ERROR_IO;
26650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
26750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
26850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return OK;
26950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
27050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
27150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber////////////////////////////////////////////////////////////////////////////////
27250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
273b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampestatic const bool kUseHexDump = false;
274b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe
27520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatic void hexdump(const void *_data, size_t size) {
27620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const uint8_t *data = (const uint8_t *)_data;
27720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t offset = 0;
27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (offset < size) {
279377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        printf("0x%04zx  ", offset);
28020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        size_t n = size - offset;
28220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (n > 16) {
28320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            n = 16;
28420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < 16; ++i) {
28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (i == 8) {
28820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(" ");
28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
29020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (offset + i < size) {
29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%02x ", data[offset + i]);
29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("   ");
29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf(" ");
29920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < n; ++i) {
30120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (isprint(data[offset + i])) {
30220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%c", data[offset + i]);
30320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
30420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(".");
30520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
30620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
30720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf("\n");
30920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        offset += 16;
31120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
31220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
31320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huberstatic const char *FourCC2MIME(uint32_t fourcc) {
31520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch (fourcc) {
31620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
31718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AAC;
31820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
32018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_NB;
32120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
322371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
32318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_WB;
324371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
32520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
32618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_MPEG4;
32720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
329e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('h', '2', '6', '3'):
330e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('H', '2', '6', '3'):
33118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_H263;
33220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
33418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_AVC;
33520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3363b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'v', 'c', '1'):
3373b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'e', 'v', '1'):
3383b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            return MEDIA_MIMETYPE_VIDEO_HEVC;
33920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
340dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(!"should not be here.");
34120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
34220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
34320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
34420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
34548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissenstatic bool AdjustChannelsAndRate(uint32_t fourcc, uint32_t *channels, uint32_t *rate) {
34648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, FourCC2MIME(fourcc))) {
34748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // AMR NB audio is always mono, 8kHz
34848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *channels = 1;
34948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *rate = 8000;
35048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return true;
35148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, FourCC2MIME(fourcc))) {
35248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // AMR WB audio is always mono, 16kHz
35348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *channels = 1;
35448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *rate = 16000;
35548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return true;
35648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
35748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    return false;
35848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen}
35948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
360693d271e62a3726689ff68f4505ba49228eb94b2Andreas HuberMPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
361c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    : mMoofOffset(0),
362928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang      mMoofFound(false),
363928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang      mMdatFound(false),
36405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mDataSource(source),
365bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber      mInitCheck(NO_INIT),
3667be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber      mHasVideo(false),
367fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen      mHeaderTimescale(0),
36820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mFirstTrack(NULL),
36972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber      mLastTrack(NULL),
370dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mFileMetaData(new MetaData),
371dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mFirstSINF(NULL),
372dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mIsDrm(false) {
37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Extractor::~MPEG4Extractor() {
37620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
37720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
37820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        Track *next = track->next;
37920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
38020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete track;
38120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = next;
38220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
38320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFirstTrack = mLastTrack = NULL;
384dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
385dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    SINF *sinf = mFirstSINF;
386dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (sinf) {
387dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        SINF *next = sinf->next;
3888da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        delete[] sinf->IPMPData;
389dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        delete sinf;
390dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf = next;
391dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
392dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    mFirstSINF = NULL;
393ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
394ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mPssh.size(); i++) {
395ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        delete [] mPssh[i].data;
396ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
39720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
39820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
39905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenuint32_t MPEG4Extractor::flags() const {
40005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return CAN_PAUSE |
40105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ((mMoofOffset == 0 || mSidxEntries.size() != 0) ?
40205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    (CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK) : 0);
40305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
40405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
4057be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Hubersp<MetaData> MPEG4Extractor::getMetaData() {
4067be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    status_t err;
4077be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    if ((err = readMetaData()) != OK) {
40872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return new MetaData;
4097be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    }
4107be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
41172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return mFileMetaData;
4127be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber}
4137be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
414693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersize_t MPEG4Extractor::countTracks() {
41520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
41620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
417ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        ALOGV("MPEG4Extractor::countTracks: no tracks");
418693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return 0;
41920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
42020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
421693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    size_t n = 0;
42220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
42320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
424693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        ++n;
42520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
42620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
42720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
428a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("MPEG4Extractor::countTracks: %zu tracks", n);
429693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    return n;
43020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
43120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4327e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Hubersp<MetaData> MPEG4Extractor::getTrackMetaData(
4337e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        size_t index, uint32_t flags) {
43420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
43520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return NULL;
43720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
43820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
44020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
44120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
44220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
44320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
44420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
44520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
44620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
44720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
44820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
449371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
450371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
451371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
452371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
4537e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    if ((flags & kIncludeExtensiveMetaData)
4547e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            && !track->includes_expensive_metadata) {
4557e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        track->includes_expensive_metadata = true;
4567e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
4577e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        const char *mime;
4587e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        CHECK(track->meta->findCString(kKeyMIMEType, &mime));
4597e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        if (!strncasecmp("video/", mime, 6)) {
46005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (mMoofOffset > 0) {
46105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                int64_t duration;
46205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (track->meta->findInt64(kKeyDuration, &duration)) {
46305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    // nothing fancy, just pick a frame near 1/4th of the duration
46405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    track->meta->setInt64(
46505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            kKeyThumbnailTime, duration / 4);
46605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
46705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            } else {
46805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t sampleIndex;
46905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t sampleTime;
47005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK
47105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        && track->sampleTable->getMetaDataForSample(
47205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            sampleIndex, NULL /* offset */, NULL /* size */,
47305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            &sampleTime) == OK) {
47405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    track->meta->setInt64(
47505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            kKeyThumbnailTime,
47605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            ((int64_t)sampleTime * 1000000) / track->timescale);
47705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
4787e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            }
4797e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        }
4807e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    }
4817e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
48220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return track->meta;
48320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
48420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
48548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissenstatic void MakeFourCCString(uint32_t x, char *s) {
48648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[0] = x >> 24;
48748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[1] = (x >> 16) & 0xff;
48848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[2] = (x >> 8) & 0xff;
48948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[3] = x & 0xff;
49048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[4] = '\0';
49148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen}
49248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
49320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Extractor::readMetaData() {
494bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    if (mInitCheck != NO_INIT) {
495bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        return mInitCheck;
49620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
49720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
498c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = 0;
49920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
500928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang    bool sawMoovOrSidx = false;
501928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang
502928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang    while (!(sawMoovOrSidx && (mMdatFound || mMoofFound))) {
503a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen        off64_t orig_offset = offset;
50405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        err = parseChunk(&offset, 0);
505a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen
5064ff2a0dbb178c4ea652f30aa4f1d3deb9fdbc832Lajos Molnar        if (err != OK && err != UNKNOWN_ERROR) {
5074ff2a0dbb178c4ea652f30aa4f1d3deb9fdbc832Lajos Molnar            break;
5084ff2a0dbb178c4ea652f30aa4f1d3deb9fdbc832Lajos Molnar        } else if (offset <= orig_offset) {
509a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            // only continue parsing if the offset was advanced,
510a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            // otherwise we might end up in an infinite loop
511ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar            ALOGE("did not advance: %lld->%lld", (long long)orig_offset, (long long)offset);
512a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            err = ERROR_MALFORMED;
513a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            break;
514928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang        } else if (err == UNKNOWN_ERROR) {
515928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang            sawMoovOrSidx = true;
51605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
51720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
5187be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
519bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    if (mInitCheck == OK) {
52072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        if (mHasVideo) {
521bc8b5faec8a0a9ad7c8d94945e7b000d63f0afe6Andreas Huber            mFileMetaData->setCString(
522bc8b5faec8a0a9ad7c8d94945e7b000d63f0afe6Andreas Huber                    kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG4);
52372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else {
52472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
52572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
526bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    } else {
527bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        mInitCheck = err;
52820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
52920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
530bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    CHECK_NE(err, (status_t)NO_INIT);
531ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
532ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // copy pssh data into file metadata
533c9b255b7f771f55462cadd34e109bfee3bf80a3aMarco Nelissen    uint64_t psshsize = 0;
534ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mPssh.size(); i++) {
535ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        psshsize += 20 + mPssh[i].datalen;
536ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
537c9b255b7f771f55462cadd34e109bfee3bf80a3aMarco Nelissen    if (psshsize > 0 && psshsize <= UINT32_MAX) {
538ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        char *buf = (char*)malloc(psshsize);
539ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        char *ptr = buf;
540ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        for (size_t i = 0; i < mPssh.size(); i++) {
541ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memcpy(ptr, mPssh[i].uuid, 20); // uuid + length
542ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memcpy(ptr + 20, mPssh[i].data, mPssh[i].datalen);
543ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ptr += (20 + mPssh[i].datalen);
544ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
545ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mFileMetaData->setData(kKeyPssh, 'pssh', buf, psshsize);
546ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        free(buf);
547ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
548bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    return mInitCheck;
54920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
55020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
551dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wangchar* MPEG4Extractor::getDrmTrackInfo(size_t trackID, int *len) {
552dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mFirstSINF == NULL) {
553dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return NULL;
554dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
555dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
556dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    SINF *sinf = mFirstSINF;
557dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (sinf && (trackID != sinf->trackID)) {
558dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf = sinf->next;
559dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
560dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
561dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (sinf == NULL) {
562dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return NULL;
563dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
564dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
565dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    *len = sinf->len;
566dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return sinf->IPMPData;
567dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
568dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
569dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang// Reads an encoded integer 7 bits at a time until it encounters the high bit clear.
57056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenstatic int32_t readSize(off64_t offset,
571dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        const sp<DataSource> DataSource, uint8_t *numOfBytes) {
572dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint32_t size = 0;
573dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t data;
574dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    bool moreData = true;
575dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    *numOfBytes = 0;
576dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
577dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (moreData) {
578dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (DataSource->readAt(offset, &data, 1) < 1) {
579dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return -1;
580dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
581dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        offset ++;
582dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        moreData = (data >= 128) ? true : false;
583dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        size = (size << 7) | (data & 0x7f); // Take last 7 bits
584dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        (*numOfBytes) ++;
585dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
586dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
587dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return size;
588dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
589dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
59084333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG4Extractor::parseDrmSINF(
59184333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        off64_t * /* offset */, off64_t data_offset) {
592dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t updateIdTag;
593dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
594dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
595dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
596dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset ++;
597dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
598dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (0x01/*OBJECT_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
599dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
600dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
601dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
602dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t numOfBytes;
603dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    int32_t size = readSize(data_offset, mDataSource, &numOfBytes);
604dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size < 0) {
605dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
606dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
607dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset += numOfBytes;
608dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
609dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while(size >= 11 ) {
610dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t descriptorTag;
611dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, &descriptorTag, 1) < 1) {
612dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
613dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
614dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset ++;
615dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
616dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (0x11/*OBJECT_DESCRIPTOR_ID_TAG*/ != descriptorTag) {
617dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
618dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
619dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
620dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t buffer[8];
621dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        //ObjectDescriptorID and ObjectDescriptor url flag
622dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, buffer, 2) < 2) {
623dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
624dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
625dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset += 2;
626dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
627dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if ((buffer[1] >> 5) & 0x0001) { //url flag is set
628dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
629dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
630dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
631dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, buffer, 8) < 8) {
632dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
633dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
634dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset += 8;
635dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
636dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if ((0x0F/*ES_ID_REF_TAG*/ != buffer[1])
637dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                || ( 0x0A/*IPMP_DESCRIPTOR_POINTER_ID_TAG*/ != buffer[5])) {
638dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
639dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
640dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
641dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        SINF *sinf = new SINF;
642dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->trackID = U16_AT(&buffer[3]);
643dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->IPMPDescriptorID = buffer[7];
644dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->next = mFirstSINF;
645dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        mFirstSINF = sinf;
646dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
647dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        size -= (8 + 2 + 1);
648dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
649dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
650dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size != 0) {
651dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
652dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
653dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
654dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
655dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
656dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
657dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset ++;
658dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
659dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if(0x05/*IPMP_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
660dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
661dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
662dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
663dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    size = readSize(data_offset, mDataSource, &numOfBytes);
664dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size < 0) {
665dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
666dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
667dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset += numOfBytes;
668dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
669dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (size > 0) {
670dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t tag;
671dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        int32_t dataLen;
672dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, &tag, 1) < 1) {
673dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
674dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
675dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset ++;
676dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
677dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (0x0B/*IPMP_DESCRIPTOR_ID_TAG*/ == tag) {
678dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            uint8_t id;
679dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            dataLen = readSize(data_offset, mDataSource, &numOfBytes);
680dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (dataLen < 0) {
681dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
682dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            } else if (dataLen < 4) {
683dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
684dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
685dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset += numOfBytes;
686dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
687dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (mDataSource->readAt(data_offset, &id, 1) < 1) {
688dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
689dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
690dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset ++;
691dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
692dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            SINF *sinf = mFirstSINF;
693dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            while (sinf && (sinf->IPMPDescriptorID != id)) {
694dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                sinf = sinf->next;
695dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
696dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (sinf == NULL) {
697dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
698dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
699dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            sinf->len = dataLen - 3;
7008da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            sinf->IPMPData = new (std::nothrow) char[sinf->len];
7018da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            if (sinf->IPMPData == NULL) {
7028da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen                return ERROR_MALFORMED;
7038da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            }
704f7df9ab3187a3c02bffe1fba10d3fb95197e4a07Ichitaro Kohara            data_offset += 2;
705dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
706f7df9ab3187a3c02bffe1fba10d3fb95197e4a07Ichitaro Kohara            if (mDataSource->readAt(data_offset, sinf->IPMPData, sinf->len) < sinf->len) {
707dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
708dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
709dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset += sinf->len;
710dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
711dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size -= (dataLen + numOfBytes + 1);
712dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
713dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
714dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
715dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size != 0) {
716dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
717dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
718dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
719dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return UNKNOWN_ERROR;  // Return a dummy error.
720dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
721dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
72272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstruct PathAdder {
72372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder(Vector<uint32_t> *path, uint32_t chunkType)
72472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        : mPath(path) {
72572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        mPath->push(chunkType);
72672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
72772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
72872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    ~PathAdder() {
72972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        mPath->pop();
73072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
73172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
73272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberprivate:
73372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    Vector<uint32_t> *mPath;
73472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
73572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder(const PathAdder &);
73672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder &operator=(const PathAdder &);
73772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber};
73872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
73972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic bool underMetaDataPath(const Vector<uint32_t> &path) {
74072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return path.size() >= 5
74172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[0] == FOURCC('m', 'o', 'o', 'v')
74272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[1] == FOURCC('u', 'd', 't', 'a')
74372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[2] == FOURCC('m', 'e', 't', 'a')
74472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[3] == FOURCC('i', 'l', 's', 't');
74572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
74672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
7478cfad968d5ec429b033caff9743f1ef15090be61Chong Zhangstatic bool underQTMetaPath(const Vector<uint32_t> &path, int32_t depth) {
7488cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    return path.size() >= 2
7498cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            && path[0] == FOURCC('m', 'o', 'o', 'v')
7508cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            && path[1] == FOURCC('m', 'e', 't', 'a')
7518cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            && (depth == 2
7528cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            || (depth == 3
753ef185e94ce624146e3b1f3cbdb2404e833a0f81dChong Zhang                    && (path[2] == FOURCC('h', 'd', 'l', 'r')
754ef185e94ce624146e3b1f3cbdb2404e833a0f81dChong Zhang                    ||  path[2] == FOURCC('i', 'l', 's', 't')
7558cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    ||  path[2] == FOURCC('k', 'e', 'y', 's'))));
7568cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang}
7578cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
75872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber// Given a time in seconds since Jan 1 1904, produce a human-readable string.
7593724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissenstatic bool convertTimeToDate(int64_t time_1904, String8 *s) {
7603724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen    // delta between mpeg4 time and unix epoch time
7613724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen    static const int64_t delta = (((66 * 365 + 17) * 24) * 3600);
7623724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen    if (time_1904 < INT64_MIN + delta) {
7633724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen        return false;
7643724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen    }
7653724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen    time_t time_1970 = time_1904 - delta;
76672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
76772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    char tmp[32];
7683724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen    struct tm* tm = gmtime(&time_1970);
7693724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen    if (tm != NULL &&
7703724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen            strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", tm) > 0) {
7713724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen        s->setTo(tmp);
7723724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen        return true;
7733724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen    }
7743724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen    return false;
77572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
77672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
777c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
778ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar    ALOGV("entering parseChunk %lld/%d", (long long)*offset, depth);
779452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen
780452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen    if (*offset < 0) {
781452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen        ALOGE("b/23540914");
782452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen        return ERROR_MALFORMED;
783452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen    }
784dd2d81b49d22642b15ac6dcbc5ad59d0c6f5c227Marco Nelissen    if (depth > 100) {
785dd2d81b49d22642b15ac6dcbc5ad59d0c6f5c227Marco Nelissen        ALOGE("b/27456299");
786dd2d81b49d22642b15ac6dcbc5ad59d0c6f5c227Marco Nelissen        return ERROR_MALFORMED;
787dd2d81b49d22642b15ac6dcbc5ad59d0c6f5c227Marco Nelissen    }
78820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t hdr[2];
78934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
79020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_IO;
79120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
79220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint64_t chunk_size = ntohl(hdr[0]);
7932d0ac425564ff9882ebaac5267d1a04d4af67d00Bernhard Rosenkränzer    int32_t chunk_type = ntohl(hdr[1]);
794c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t data_offset = *offset + 8;
79520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
79620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (chunk_size == 1) {
79734769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
79820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_IO;
79920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
80020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        chunk_size = ntoh64(chunk_size);
80120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        data_offset += 8;
80271b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber
80371b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        if (chunk_size < 16) {
80471b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber            // The smallest valid chunk is 16 bytes long in this case.
80571b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber            return ERROR_MALFORMED;
80671b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        }
807a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen    } else if (chunk_size == 0) {
808a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen        if (depth == 0) {
809a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            // atom extends to end of file
810a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            off64_t sourceSize;
811a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            if (mDataSource->getSize(&sourceSize) == OK) {
812a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen                chunk_size = (sourceSize - *offset);
813a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            } else {
814a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen                // XXX could we just pick a "sufficiently large" value here?
815a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen                ALOGE("atom size is 0, and data source has no size");
816a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen                return ERROR_MALFORMED;
817a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            }
818a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen        } else {
819a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            // not allowed for non-toplevel atoms, skip it
820a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            *offset += 4;
821a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            return OK;
822a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen        }
82371b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber    } else if (chunk_size < 8) {
82471b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        // The smallest valid chunk is 8 bytes long.
825a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGE("invalid chunk size: %" PRIu64, chunk_size);
82671b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        return ERROR_MALFORMED;
82720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
82820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
82920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    char chunk[5];
83020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MakeFourCCString(chunk_type, chunk);
831ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar    ALOGV("chunk: %s @ %lld, %d", chunk, (long long)*offset, depth);
83220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
833b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    if (kUseHexDump) {
834b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        static const char kWhitespace[] = "                                        ";
835b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
836b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        printf("%sfound chunk '%s' of size %" PRIu64 "\n", indent, chunk, chunk_size);
83720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
838b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        char buffer[256];
839b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        size_t n = chunk_size;
840b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        if (n > sizeof(buffer)) {
841b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe            n = sizeof(buffer);
842b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        }
843b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        if (mDataSource->readAt(*offset, buffer, n)
844b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                < (ssize_t)n) {
845b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe            return ERROR_IO;
846b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        }
847ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
848b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        hexdump(buffer, n);
849b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    }
85020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
85172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder autoAdder(&mPath, chunk_type);
85272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
853452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen    // (data_offset - *offset) is either 8 or 16
854452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen    off64_t chunk_data_size = chunk_size - (data_offset - *offset);
855452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen    if (chunk_data_size < 0) {
856452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen        ALOGE("b/23540914");
857452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen        return ERROR_MALFORMED;
858452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen    }
85920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
86072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (chunk_type != FOURCC('c', 'p', 'r', 't')
861515e855eae78aa495da58356486aaa666cb57fd1James Dong            && chunk_type != FOURCC('c', 'o', 'v', 'r')
86272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            && mPath.size() == 5 && underMetaDataPath(mPath)) {
863c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t stop_offset = *offset + chunk_size;
86472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        *offset = data_offset;
86572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        while (*offset < stop_offset) {
86672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            status_t err = parseChunk(offset, depth + 1);
86772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (err != OK) {
86872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return err;
86972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
87072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
871bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
872bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (*offset != stop_offset) {
873bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
874bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
87572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
87672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return OK;
87772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
87872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
87920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch(chunk_type) {
88020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'v'):
88120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'k'):
88220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'i', 'a'):
88320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'i', 'n', 'f'):
88420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('d', 'i', 'n', 'f'):
88520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'b', 'l'):
88620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'v', 'e', 'x'):
88720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'f'):
88820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'f'):
88920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'f', 'r', 'a'):
89072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('u', 'd', 't', 'a'):
89172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('i', 'l', 's', 't'):
892ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'i', 'n', 'f'):
893ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'c', 'h', 'i'):
8940a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        case FOURCC('e', 'd', 't', 's'):
89520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
896928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang            if (chunk_type == FOURCC('m', 'o', 'o', 'f') && !mMoofFound) {
897928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang                // store the offset of the first segment
898928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang                mMoofFound = true;
899928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang                mMoofOffset = *offset;
900928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang            }
901928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang
90250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
903a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                ALOGV("sampleTable chunk is %" PRIu64 " bytes long.", chunk_size);
90450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
905b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                if (mDataSource->flags()
906b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                        & (DataSource::kWantsPrefetching
907b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                            | DataSource::kIsCachingDataSource)) {
90850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    sp<MPEG4DataSource> cachedSource =
90950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                        new MPEG4DataSource(mDataSource);
91050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
91150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
91250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                        mDataSource = cachedSource;
91350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    }
91450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                }
9151edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber
916f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                if (mLastTrack == NULL)
917f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                    return ERROR_MALFORMED;
918f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
9191edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber                mLastTrack->sampleTable = new SampleTable(mDataSource);
92050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            }
92150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
9226f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber            bool isTrack = false;
923bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (chunk_type == FOURCC('t', 'r', 'a', 'k')) {
9246f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                isTrack = true;
9256f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
926bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                Track *track = new Track;
927bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->next = NULL;
928bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                if (mLastTrack) {
929bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    mLastTrack->next = track;
930bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                } else {
931bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    mFirstTrack = track;
932bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                }
933bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                mLastTrack = track;
934bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
935bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->meta = new MetaData;
936bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->includes_expensive_metadata = false;
9376f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                track->skipTrack = false;
938bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->timescale = 0;
939bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->meta->setCString(kKeyMIMEType, "application/octet-stream");
940bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
941bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
942c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
94320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset;
94420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
94520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
94620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
94720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
94820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
94920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
95020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
951bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
952bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
953bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
954bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
9556f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber            if (isTrack) {
9560386c91b8a910a134e5898ffa924c1b6c7560b13Wei Jia                int32_t trackId;
9570386c91b8a910a134e5898ffa924c1b6c7560b13Wei Jia                // There must be exact one track header per track.
9580386c91b8a910a134e5898ffa924c1b6c7560b13Wei Jia                if (!mLastTrack->meta->findInt32(kKeyTrackID, &trackId)) {
9590386c91b8a910a134e5898ffa924c1b6c7560b13Wei Jia                    mLastTrack->skipTrack = true;
9600386c91b8a910a134e5898ffa924c1b6c7560b13Wei Jia                }
9616f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                if (mLastTrack->skipTrack) {
9626f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    Track *cur = mFirstTrack;
9636f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
9646f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    if (cur == mLastTrack) {
9656f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        delete cur;
9666f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        mFirstTrack = mLastTrack = NULL;
9676f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    } else {
9686f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        while (cur && cur->next != mLastTrack) {
9696f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                            cur = cur->next;
9706f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        }
9716f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        cur->next = NULL;
9726f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        delete mLastTrack;
9736f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        mLastTrack = cur;
9746f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    }
9756f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
9766f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    return OK;
9776f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                }
9786f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
979bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                status_t err = verifyTrack(mLastTrack);
980bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
981bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                if (err != OK) {
982bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    return err;
983bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                }
984bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
985bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                mInitCheck = OK;
98620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
987dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                if (!mIsDrm) {
988dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return UNKNOWN_ERROR;  // Return a dummy error.
989dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                } else {
990dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return OK;
991dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
99220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
99320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
99420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
99520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9960a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        case FOURCC('e', 'l', 's', 't'):
9970a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        {
9980517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
9990517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
10000a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            // See 14496-12 8.6.6
10010a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            uint8_t version;
10020a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (mDataSource->readAt(data_offset, &version, 1) < 1) {
10030a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                return ERROR_IO;
10040a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
10050a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
10060a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            uint32_t entry_count;
10070a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (!mDataSource->getUInt32(data_offset + 4, &entry_count)) {
10080a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                return ERROR_IO;
10090a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
10100a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
10110a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (entry_count != 1) {
10120a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                // we only support a single entry at the moment, for gapless playback
10130a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                ALOGW("ignoring edit list with %d entries", entry_count);
1014fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            } else if (mHeaderTimescale == 0) {
1015210efd48ed21ca0084d9440f9a1db7d9878f8094Marco Nelissen                ALOGW("ignoring edit list because timescale is 0");
10160a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            } else {
10170a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                off64_t entriesoffset = data_offset + 8;
10180a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                uint64_t segment_duration;
10190a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int64_t media_time;
10200a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
10210a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                if (version == 1) {
10220a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    if (!mDataSource->getUInt64(entriesoffset, &segment_duration) ||
10230a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                            !mDataSource->getUInt64(entriesoffset + 8, (uint64_t*)&media_time)) {
10240a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        return ERROR_IO;
10250a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    }
10260a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                } else if (version == 0) {
10270a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    uint32_t sd;
10280a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int32_t mt;
10290a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    if (!mDataSource->getUInt32(entriesoffset, &sd) ||
10300a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                            !mDataSource->getUInt32(entriesoffset + 4, (uint32_t*)&mt)) {
10310a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        return ERROR_IO;
10320a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    }
10330a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    segment_duration = sd;
10340a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    media_time = mt;
10350a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                } else {
10360a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    return ERROR_IO;
10370a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                }
10380a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
1039fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                uint64_t halfscale = mHeaderTimescale / 2;
1040fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                segment_duration = (segment_duration * 1000000 + halfscale)/ mHeaderTimescale;
1041fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                media_time = (media_time * 1000000 + halfscale) / mHeaderTimescale;
10420a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
10430a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int64_t duration;
10440a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int32_t samplerate;
10451391f933b49cfb56da9aa63f723de83b076cf888Robert Shih                if (!mLastTrack) {
10461391f933b49cfb56da9aa63f723de83b076cf888Robert Shih                    return ERROR_MALFORMED;
10471391f933b49cfb56da9aa63f723de83b076cf888Robert Shih                }
10480a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                if (mLastTrack->meta->findInt64(kKeyDuration, &duration) &&
10490a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        mLastTrack->meta->findInt32(kKeySampleRate, &samplerate)) {
10500a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
10510a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t delay = (media_time  * samplerate + 500000) / 1000000;
10520a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
10530a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
1054608fe1d6b2ea4d88245a109afe2bfba580881a16Wei Jia                    int64_t paddingus = duration - (int64_t)(segment_duration + media_time);
1055465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                    if (paddingus < 0) {
1056465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        // track duration from media header (which is what kKeyDuration is) might
1057465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        // be slightly shorter than the segment duration, which would make the
1058465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        // padding negative. Clamp to zero.
1059465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        paddingus = 0;
1060465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                    }
10610a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t paddingsamples = (paddingus * samplerate + 500000) / 1000000;
10620a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    mLastTrack->meta->setInt32(kKeyEncoderPadding, paddingsamples);
10630a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                }
10640a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
10650a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            break;
10660a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        }
10670a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
1068ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('f', 'r', 'm', 'a'):
1069ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
10700517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
10710517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
107248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t original_fourcc;
1073ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset, &original_fourcc, 4) < 4) {
1074ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1075ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1076ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            original_fourcc = ntohl(original_fourcc);
1077ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("read original format: %d", original_fourcc);
1078f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
1079f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1080f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1081f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
1082ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc));
108348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t num_channels = 0;
108448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t sample_rate = 0;
108548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (AdjustChannelsAndRate(original_fourcc, &num_channels, &sample_rate)) {
108648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
108748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
108848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            }
1089ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1090ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1091ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1092ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('t', 'e', 'n', 'c'):
1093ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
10940517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
10950517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1096ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (chunk_size < 32) {
1097ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1098ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1099ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1100ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // tenc box contains 1 byte version, 3 byte flags, 3 byte default algorithm id, one byte
1101ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // default IV size, 16 bytes default KeyID
1102ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // (ISO 23001-7)
1103ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            char buf[4];
1104ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memset(buf, 0, 4);
1105ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 4, buf + 1, 3) < 3) {
1106ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1107ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1108ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t defaultAlgorithmId = ntohl(*((int32_t*)buf));
1109ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (defaultAlgorithmId > 1) {
1110ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only 0 (clear) and 1 (AES-128) are valid
1111ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1112ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1113ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1114ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memset(buf, 0, 4);
1115ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 7, buf + 3, 1) < 1) {
1116ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1117ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1118ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t defaultIVSize = ntohl(*((int32_t*)buf));
1119ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1120ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((defaultAlgorithmId == 0 && defaultIVSize != 0) ||
1121ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    (defaultAlgorithmId != 0 && defaultIVSize == 0)) {
1122ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only unencrypted data must have 0 IV size
1123ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1124ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            } else if (defaultIVSize != 0 &&
1125ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    defaultIVSize != 8 &&
1126ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    defaultIVSize != 16) {
1127ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only supported sizes are 0, 8 and 16
1128ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1129ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1130ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1131ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint8_t defaultKeyId[16];
1132ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1133ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 8, &defaultKeyId, 16) < 16) {
1134ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1135ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1136ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1137f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1138f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1139f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
1140ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setInt32(kKeyCryptoMode, defaultAlgorithmId);
1141ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setInt32(kKeyCryptoDefaultIVSize, defaultIVSize);
1142ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setData(kKeyCryptoKey, 'tenc', defaultKeyId, 16);
1143ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1144ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1145ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
114620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'k', 'h', 'd'):
114720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
11480517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
11490517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1150ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            status_t err;
1151ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) {
1152ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber                return err;
115320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
115420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
115520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
115620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
115720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1158ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('p', 's', 's', 'h'):
1159ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
11600517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
11610517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1162ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            PsshInfo pssh;
1163ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1164ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 4, &pssh.uuid, 16) < 16) {
1165ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1166ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1167ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1168ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t psshdatalen = 0;
1169ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 20, &psshdatalen, 4) < 4) {
1170ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1171ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1172ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            pssh.datalen = ntohl(psshdatalen);
1173ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("pssh data size: %d", pssh.datalen);
1174c9b255b7f771f55462cadd34e109bfee3bf80a3aMarco Nelissen            if (chunk_size < 20 || pssh.datalen > chunk_size - 20) {
1175ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // pssh data length exceeds size of containing box
1176ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1177ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1178ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
11798da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            pssh.data = new (std::nothrow) uint8_t[pssh.datalen];
11808da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            if (pssh.data == NULL) {
11818da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen                return ERROR_MALFORMED;
11828da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            }
1183ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("allocated pssh @ %p", pssh.data);
1184ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ssize_t requested = (ssize_t) pssh.datalen;
1185ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 24, pssh.data, requested) < requested) {
1186ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1187ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1188ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mPssh.push_back(pssh);
1189ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1190ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1191ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1192ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
119320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'h', 'd'):
119420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
11950517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
11960517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1197202fbed96db40ec5fb43d633fc97601a15a6dd7aRobert Shih            if (chunk_data_size < 4 || mLastTrack == NULL) {
119820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
119920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
120020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
120120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t version;
120234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
120320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, &version, sizeof(version))
120420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(version)) {
120520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
120620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
120720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1208c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t timescale_offset;
120920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
121020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
121120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 16;
121220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else if (version == 0) {
121320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 8;
121420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
121520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
121620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
121720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
121820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t timescale;
121934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
122020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        timescale_offset, &timescale, sizeof(timescale))
122120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(timescale)) {
122220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
122320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
122420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12252e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang            if (!timescale) {
12262e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang                ALOGE("timescale should not be ZERO.");
12272e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang                return ERROR_MALFORMED;
12282e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang            }
12292e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang
123020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->timescale = ntohl(timescale);
123120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1232c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            // 14496-12 says all ones means indeterminate, but some files seem to use
1233c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            // 0 instead. We treat both the same.
123405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            int64_t duration = 0;
123520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
123634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
123720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration, sizeof(duration))
123820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration)) {
123920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
124020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
1241c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (duration != -1) {
1242c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    duration = ntoh64(duration);
1243c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
124420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
124505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t duration32;
124634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
124720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration32, sizeof(duration32))
124820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration32)) {
124920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
125020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
125105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (duration32 != 0xffffffff) {
125205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    duration = ntohl(duration32);
125305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
125420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1255e3e82d54c51a3130badcd9e433fe808d965f15c2Joshua J. Drake            if (duration != 0 && mLastTrack->timescale != 0) {
1256c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mLastTrack->meta->setInt64(
1257c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                        kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
1258c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
125920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12607a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            uint8_t lang[2];
12617a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            off64_t lang_offset;
12627a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            if (version == 1) {
12637a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                lang_offset = timescale_offset + 4 + 8;
12647a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            } else if (version == 0) {
12657a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                lang_offset = timescale_offset + 4 + 4;
12667a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            } else {
12677a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                return ERROR_IO;
12687a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            }
12697a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
12707a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            if (mDataSource->readAt(lang_offset, &lang, sizeof(lang))
12717a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                    < (ssize_t)sizeof(lang)) {
12727a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                return ERROR_IO;
12737a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            }
12747a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
12757a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // To get the ISO-639-2/T three character language code
12767a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // 1 bit pad followed by 3 5-bits characters. Each character
12777a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // is packed as the difference between its ASCII value and 0x60.
12787a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            char lang_code[4];
12797a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[0] = ((lang[0] >> 2) & 0x1f) + 0x60;
12807a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[1] = ((lang[0] & 0x3) << 3 | (lang[1] >> 5)) + 0x60;
12817a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[2] = (lang[1] & 0x1f) + 0x60;
12827a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[3] = '\0';
12837a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
12847a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            mLastTrack->meta->setCString(
12857a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                    kKeyMediaLanguage, lang_code);
12867a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
128720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
128820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
128920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
129020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'd'):
129120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
129220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 8) {
129320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
129420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
129520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
129620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8];
1297c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size < (off64_t)sizeof(buffer)) {
1298bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1299bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
1300bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
130134769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
130220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, 8) < 8) {
130320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
130420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
130520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
130620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
130720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
130820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
130920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
131020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
131120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t entry_count = U32_AT(&buffer[4]);
131220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
131320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (entry_count > 1) {
13143b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // For 3GPP timed text, there could be multiple tx3g boxes contain
13153b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // multiple text display formats. These formats will be used to
13163b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // display the timed text.
1317ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // For encrypted files, there may also be more than one entry.
13183b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                const char *mime;
1319f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
1320f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                if (mLastTrack == NULL)
1321f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                    return ERROR_MALFORMED;
1322f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
13233b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1324ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) &&
1325ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                        strcasecmp(mime, "application/octet-stream")) {
13263b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    // For now we only support a single type of media per track.
13273b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    mLastTrack->skipTrack = true;
13283b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    *offset += chunk_size;
13293b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    break;
13303b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                }
133120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1332c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
133320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + 8;
133420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            for (uint32_t i = 0; i < entry_count; ++i) {
133520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
133620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
133720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
133820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
133920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1340bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1341bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1342bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1343bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
134420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
134520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
134620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
134720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
134848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        case FOURCC('e', 'n', 'c', 'a'):
134920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
1350371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
135120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
135220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8 + 20];
135320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
135420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic AudioSampleEntry size.
135520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
135720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
135834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
135920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
136020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
136120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
136220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1363b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe            uint16_t data_ref_index __unused = U16_AT(&buffer[6]);
136448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t num_channels = U16_AT(&buffer[16]);
136520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
136681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint16_t sample_size = U16_AT(&buffer[18]);
136781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
136881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
1369f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1370f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1371f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
137248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (chunk_type != FOURCC('e', 'n', 'c', 'a')) {
137348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                // if the chunk type is enca, we'll get the type from the sinf/frma box later
137448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
137548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate);
137620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
137748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            ALOGV("*** coding='%s' %d channels, size %d, rate %d\n",
137881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                   chunk, num_channels, sample_size, sample_rate);
137920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
138020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
138120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1382c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
138320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
138420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
138520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
138620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
138720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
138820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
138920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1390bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1391bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1392bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1393bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
139420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
139520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
139620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
139720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
1398ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('e', 'n', 'c', 'v'):
139920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
1400e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('H', '2', '6', '3'):
1401e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('h', '2', '6', '3'):
140220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
14033b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'v', 'c', '1'):
14043b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'e', 'v', '1'):
140520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
14067be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber            mHasVideo = true;
14077be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
140820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[78];
140920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
141020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic VideoSampleEntry size.
141120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
141220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
141320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
141434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
141520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
141620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
141720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
141820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1419b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe            uint16_t data_ref_index __unused = U16_AT(&buffer[6]);
142020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t width = U16_AT(&buffer[6 + 18]);
142120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t height = U16_AT(&buffer[6 + 20]);
142220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1423ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // The video sample is not standard-compliant if it has invalid dimension.
1424a6256238d9015c42129fe43791968768fe501efaJames Dong            // Use some default width and height value, and
1425a6256238d9015c42129fe43791968768fe501efaJames Dong            // let the decoder figure out the actual width and height (and thus
1426a6256238d9015c42129fe43791968768fe501efaJames Dong            // be prepared for INFO_FOMRAT_CHANGED event).
1427a6256238d9015c42129fe43791968768fe501efaJames Dong            if (width == 0)  width  = 352;
1428a6256238d9015c42129fe43791968768fe501efaJames Dong            if (height == 0) height = 288;
1429a6256238d9015c42129fe43791968768fe501efaJames Dong
1430134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            // printf("*** coding='%s' width=%d height=%d\n",
1431134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            //        chunk, width, height);
143220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1433f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1434f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1435f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
1436ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (chunk_type != FOURCC('e', 'n', 'c', 'v')) {
1437ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // if the chunk type is encv, we'll get the type from the sinf/frma box later
1438ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
1439ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
144020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyWidth, width);
144120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyHeight, height);
144220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1443c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
144420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
144520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
144620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
144720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
144820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
144920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
145020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1451bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1452bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1453bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1454bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
145520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
145620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
145720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
145820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'c', 'o'):
145920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('c', 'o', '6', '4'):
146020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1461274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
1462274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake                return ERROR_MALFORMED;
1463274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake
146420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
146520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setChunkOffsetParams(
146620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
146720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14680517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
14690517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
147020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
147120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
147220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
147320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
147420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
147520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
147620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
147720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'c'):
147820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1479274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
1480274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake                return ERROR_MALFORMED;
1481274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake
148220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
148320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleToChunkParams(
148420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
148520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14860517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
14870517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
148820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
148920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
149020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
149120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
149220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
149320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
149420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
149520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'z'):
149620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'z', '2'):
149720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1498274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
1499274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake                return ERROR_MALFORMED;
1500274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake
150120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
150220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleSizeParams(
150320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
150420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15050517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
15060517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
150720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
150820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
150920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
151020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1511738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            size_t max_size;
151249110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            err = mLastTrack->sampleTable->getMaxSampleSize(&max_size);
151349110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber
151449110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            if (err != OK) {
151549110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber                return err;
151649110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            }
1517738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber
151805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (max_size != 0) {
151905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // Assume that a given buffer only contains at most 10 chunks,
152005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // each chunk originally prefixed with a 2 byte length will
152105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
152205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // and thus will grow by 2 bytes per chunk.
1523beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                if (max_size > SIZE_MAX - 10 * 2) {
1524beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                    ALOGE("max sample size too big: %zu", max_size);
1525beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                    return ERROR_MALFORMED;
1526beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                }
152705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
152805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            } else {
152905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // No size was specified. Pick a conservatively large size.
1530beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                uint32_t width, height;
1531beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                if (!mLastTrack->meta->findInt32(kKeyWidth, (int32_t*)&width) ||
1532beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                    !mLastTrack->meta->findInt32(kKeyHeight,(int32_t*) &height)) {
153305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ALOGE("No width or height, assuming worst case 1080p");
1534f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    width = 1920;
1535f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    height = 1080;
1536beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                } else {
1537beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                    // A resolution was specified, check that it's not too big. The values below
1538beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                    // were chosen so that the calculations below don't cause overflows, they're
1539beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                    // not indicating that resolutions up to 32kx32k are actually supported.
1540beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                    if (width > 32768 || height > 32768) {
1541beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                        ALOGE("can't support %u x %u video", width, height);
1542beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                        return ERROR_MALFORMED;
1543beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                    }
154405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
1545f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar
15464256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen                const char *mime;
15474256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1548f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
1549f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // AVC requires compression ratio of at least 2, and uses
1550f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // macroblocks
1551f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    max_size = ((width + 15) / 16) * ((height + 15) / 16) * 192;
1552f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                } else {
1553f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // For all other formats there is no minimum compression
1554f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // ratio. Use compression ratio of 1.
1555f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    max_size = width * height * 3 / 2;
155605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
1557f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size);
155805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
1559113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong
15604256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            // NOTE: setting another piece of metadata invalidates any pointers (such as the
15614256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            // mimetype) previously obtained, so don't cache them.
1562113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            const char *mime;
1563113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1564113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            // Calculate average frame rate.
1565113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            if (!strncasecmp("video/", mime, 6)) {
1566113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                size_t nSamples = mLastTrack->sampleTable->countSamples();
1567113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                int64_t durationUs;
1568113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                if (mLastTrack->meta->findInt64(kKeyDuration, &durationUs)) {
1569113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                    if (durationUs > 0) {
1570113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                        int32_t frameRate = (nSamples * 1000000LL +
1571113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                                    (durationUs >> 1)) / durationUs;
1572113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                        mLastTrack->meta->setInt32(kKeyFrameRate, frameRate);
1573113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                    }
1574113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                }
1575113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            }
1576113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong
157720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
157820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
157920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
158020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 't', 's'):
158120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1582274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
1583274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake                return ERROR_MALFORMED;
1584274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake
15850517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
15860517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
158720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
158820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setTimeToSampleParams(
158920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
159020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
159120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
159220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
159320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
159420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
159520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
159620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
159720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15984931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        case FOURCC('c', 't', 't', 's'):
15994931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        {
1600274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
1601274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake                return ERROR_MALFORMED;
1602274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake
16030517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
16040517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
16054931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            status_t err =
16064931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                mLastTrack->sampleTable->setCompositionTimeToSampleParams(
16074931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                        data_offset, chunk_data_size);
16084931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
16094931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            if (err != OK) {
16104931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                return err;
16114931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            }
16124931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
16134931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            break;
16144931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        }
16154931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
161620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 's'):
161720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1618274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
1619274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake                return ERROR_MALFORMED;
1620274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake
16210517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
16220517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
162320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
162420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSyncSampleParams(
162520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
162620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
162720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
162820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
162920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
163020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
163120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
163220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
163320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1634afd492436efc7f66b958da14659b52232efa5910Marco Nelissen        // \xA9xyz
1635e1b2ccf317301af42bb4b6631a3bcd7d8f519d00Chih-Hung Hsieh        case FOURCC(0xA9, 'x', 'y', 'z'):
16364948818cb91176df74c972ac27b2f392b5d148bcJames Dong        {
16370517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
16380517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1639afd492436efc7f66b958da14659b52232efa5910Marco Nelissen            // Best case the total data length inside "\xA9xyz" box
1640afd492436efc7f66b958da14659b52232efa5910Marco Nelissen            // would be 8, for instance "\xA9xyz" + "\x00\x04\x15\xc7" + "0+0/",
16414948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // where "\x00\x04" is the text string length with value = 4,
16424948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // "\0x15\xc7" is the language code = en, and "0+0" is a
16434948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // location (string) value with longitude = 0 and latitude = 0.
16444948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (chunk_data_size < 8) {
16454948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_MALFORMED;
16464948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
16474948818cb91176df74c972ac27b2f392b5d148bcJames Dong
16484948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Worst case the location string length would be 18,
16494948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // for instance +90.0000-180.0000, without the trailing "/" and
16504948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // the string length + language code.
16514948818cb91176df74c972ac27b2f392b5d148bcJames Dong            char buffer[18];
16524948818cb91176df74c972ac27b2f392b5d148bcJames Dong
16534948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Substracting 5 from the data size is because the text string length +
16544948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // language code takes 4 bytes, and the trailing slash "/" takes 1 byte.
16554948818cb91176df74c972ac27b2f392b5d148bcJames Dong            off64_t location_length = chunk_data_size - 5;
16564948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (location_length >= (off64_t) sizeof(buffer)) {
16574948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_MALFORMED;
16584948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
16594948818cb91176df74c972ac27b2f392b5d148bcJames Dong
16604948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (mDataSource->readAt(
16614948818cb91176df74c972ac27b2f392b5d148bcJames Dong                        data_offset + 4, buffer, location_length) < location_length) {
16624948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_IO;
16634948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
16644948818cb91176df74c972ac27b2f392b5d148bcJames Dong
16654948818cb91176df74c972ac27b2f392b5d148bcJames Dong            buffer[location_length] = '\0';
16664948818cb91176df74c972ac27b2f392b5d148bcJames Dong            mFileMetaData->setCString(kKeyLocation, buffer);
16674948818cb91176df74c972ac27b2f392b5d148bcJames Dong            break;
16684948818cb91176df74c972ac27b2f392b5d148bcJames Dong        }
16694948818cb91176df74c972ac27b2f392b5d148bcJames Dong
167020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('e', 's', 'd', 's'):
167120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
16720517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
16730517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
167420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
167520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
167620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
167720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
167820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[256];
1679c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size > (off64_t)sizeof(buffer)) {
168020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
168120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
168220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
168334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
168420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
168520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
168620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
168720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
168820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
168920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
169020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
169120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
169220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1693f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1694f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1695f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
169620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
169720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
169820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1699ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            if (mPath.size() >= 2
1700ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
1701ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // Information from the ESDS must be relied on for proper
1702ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // setup of sample rate and channel count for MPEG4 Audio.
1703ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // The generic header appears to only contain generic
1704ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // information...
1705ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1706ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio(
1707ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                        &buffer[4], chunk_data_size - 4);
1708ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1709ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                if (err != OK) {
1710ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    return err;
1711ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                }
1712ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            }
1713ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar            if (mPath.size() >= 2
1714ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                    && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'v')) {
1715ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                // Check if the video is MPEG2
1716ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                ESDS esds(&buffer[4], chunk_data_size - 4);
1717ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar
1718ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                uint8_t objectTypeIndication;
1719ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                if (esds.getObjectTypeIndication(&objectTypeIndication) == OK) {
1720ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                    if (objectTypeIndication >= 0x60 && objectTypeIndication <= 0x65) {
1721ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                        mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG2);
1722ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                    }
1723ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                }
1724ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar            }
172520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
172620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
172720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
172820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', 'C'):
172920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
17300517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
17310517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1732d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson            sp<ABuffer> buffer = new ABuffer(chunk_data_size);
173320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
173434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
1735d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson                        data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
173620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
173720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
173820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1739f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1740f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1741f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
174220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
1743d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson                    kKeyAVCC, kTypeAVCC, buffer->data(), chunk_data_size);
174420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
174520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
174620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
17473b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'v', 'c', 'C'):
17483b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        {
17493b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            sp<ABuffer> buffer = new ABuffer(chunk_data_size);
17503b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
17513b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            if (mDataSource->readAt(
17523b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar                        data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
17533b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar                return ERROR_IO;
17543b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            }
17553b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
1756f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1757f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1758f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
17593b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            mLastTrack->meta->setData(
17603b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar                    kKeyHVCC, kTypeHVCC, buffer->data(), chunk_data_size);
17613b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
17623b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            *offset += chunk_size;
17633b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            break;
17643b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        }
176520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1766244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        case FOURCC('d', '2', '6', '3'):
1767244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        {
17680517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
176917e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            /*
177017e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * d263 contains a fixed 7 bytes part:
177117e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   vendor - 4 bytes
177217e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   version - 1 byte
177317e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   level - 1 byte
177417e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   profile - 1 byte
177517e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * optionally, "d263" box itself may contain a 16-byte
177617e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * bit rate box (bitr)
177717e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   average bit rate - 4 bytes
177817e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   max bit rate - 4 bytes
177917e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             */
178017e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            char buffer[23];
178117e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            if (chunk_data_size != 7 &&
178217e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong                chunk_data_size != 23) {
1783ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar                ALOGE("Incorrect D263 box size %lld", (long long)chunk_data_size);
1784244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                return ERROR_MALFORMED;
1785244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            }
1786244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1787244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            if (mDataSource->readAt(
1788244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                    data_offset, buffer, chunk_data_size) < chunk_data_size) {
1789244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                return ERROR_IO;
1790244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            }
1791244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1792f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1793f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1794f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
1795244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size);
1796244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1797244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            break;
1798244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        }
1799244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
180072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'e', 't', 'a'):
180172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
18028cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            off64_t stop_offset = *offset + chunk_size;
18038cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            *offset = data_offset;
18048cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            bool isParsingMetaKeys = underQTMetaPath(mPath, 2);
18058cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            if (!isParsingMetaKeys) {
18068cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                uint8_t buffer[4];
18078cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                if (chunk_data_size < (off64_t)sizeof(buffer)) {
18088ee368522ca7df126033a05dc3c430182b4495c9Marco Nelissen                    *offset = stop_offset;
18098cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    return ERROR_MALFORMED;
18108cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                }
1811bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
18128cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                if (mDataSource->readAt(
18138cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                            data_offset, buffer, 4) < 4) {
18148ee368522ca7df126033a05dc3c430182b4495c9Marco Nelissen                    *offset = stop_offset;
18158cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    return ERROR_IO;
18168cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                }
181772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
18188cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                if (U32_AT(buffer) != 0) {
18198cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    // Should be version 0, flags 0.
1820ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
18218cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    // If it's not, let's assume this is one of those
18228cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    // apparently malformed chunks that don't have flags
18238cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    // and completely different semantics than what's
18248cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    // in the MPEG4 specs and skip it.
18258ee368522ca7df126033a05dc3c430182b4495c9Marco Nelissen                    *offset = stop_offset;
18268cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    return OK;
18278cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                }
18288cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                *offset +=  sizeof(buffer);
182972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
183072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
183172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            while (*offset < stop_offset) {
183272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                status_t err = parseChunk(offset, depth + 1);
183372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
183472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
183572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
183672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
1837bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1838bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1839bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1840bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
184172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
184272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
184372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
18445d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('m', 'e', 'a', 'n'):
18455d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('n', 'a', 'm', 'e'):
184672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('d', 'a', 't', 'a'):
184772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
18480517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
18490517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
185072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mPath.size() == 6 && underMetaDataPath(mPath)) {
1851fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                status_t err = parseITunesMetaData(data_offset, chunk_data_size);
185272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
185372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
185472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
185572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
185672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
185772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
185872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
185972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
186072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
186172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'v', 'h', 'd'):
186272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
18630517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
18640517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1865c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (chunk_data_size < 32) {
186672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_MALFORMED;
186772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
186872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1869c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            uint8_t header[32];
187072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
187172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, header, sizeof(header))
187272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    < (ssize_t)sizeof(header)) {
187372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
187472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
187572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1876fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            uint64_t creationTime;
1877c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            uint64_t duration = 0;
187872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (header[0] == 1) {
187972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U64_AT(&header[4]);
1880fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                mHeaderTimescale = U32_AT(&header[20]);
1881c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                duration = U64_AT(&header[24]);
1882c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (duration == 0xffffffffffffffff) {
1883c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    duration = 0;
1884c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1885bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (header[0] != 0) {
1886bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
188772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            } else {
188872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U32_AT(&header[4]);
1889fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                mHeaderTimescale = U32_AT(&header[12]);
1890c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                uint32_t d32 = U32_AT(&header[16]);
1891c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (d32 == 0xffffffff) {
1892c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    d32 = 0;
1893c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1894c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                duration = d32;
1895c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
18963724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen            if (duration != 0 && mHeaderTimescale != 0 && duration < UINT64_MAX / 1000000) {
1897c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mFileMetaData->setInt64(kKeyDuration, duration * 1000000 / mHeaderTimescale);
189872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
189972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
190072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            String8 s;
19013724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen            if (convertTimeToDate(creationTime, &s)) {
19023724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen                mFileMetaData->setCString(kKeyDate, s.string());
19033724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen            }
190472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
190572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
190672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
190772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
190872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1909c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        case FOURCC('m', 'e', 'h', 'd'):
1910c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        {
1911c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            *offset += chunk_size;
1912c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1913c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (chunk_data_size < 8) {
1914c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_MALFORMED;
1915c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1916c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1917c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            uint8_t flags[4];
1918c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (mDataSource->readAt(
1919c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                        data_offset, flags, sizeof(flags))
1920c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    < (ssize_t)sizeof(flags)) {
1921c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_IO;
1922c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1923c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1924c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            uint64_t duration = 0;
1925c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (flags[0] == 1) {
1926c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                // 64 bit
1927c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (chunk_data_size < 12) {
1928c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    return ERROR_MALFORMED;
1929c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1930c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mDataSource->getUInt64(data_offset + 4, &duration);
1931c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (duration == 0xffffffffffffffff) {
1932c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    duration = 0;
1933c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1934c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            } else if (flags[0] == 0) {
1935c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                // 32 bit
1936c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                uint32_t d32;
1937c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mDataSource->getUInt32(data_offset + 4, &d32);
1938c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (d32 == 0xffffffff) {
1939c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    d32 = 0;
1940c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1941c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                duration = d32;
1942c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            } else {
1943c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_MALFORMED;
1944c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1945c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1946e3e82d54c51a3130badcd9e433fe808d965f15c2Joshua J. Drake            if (duration != 0 && mHeaderTimescale != 0) {
1947c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mFileMetaData->setInt64(kKeyDuration, duration * 1000000 / mHeaderTimescale);
1948c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1949c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1950c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            break;
1951c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        }
1952c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1953dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        case FOURCC('m', 'd', 'a', 't'):
1954dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        {
1955ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("mdat chunk, drm: %d", mIsDrm);
1956928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang
1957928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang            mMdatFound = true;
1958928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang
1959dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (!mIsDrm) {
1960dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                *offset += chunk_size;
1961dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                break;
1962dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
1963dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
1964dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (chunk_size < 8) {
1965dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
1966dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
1967dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
1968dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return parseDrmSINF(offset, data_offset);
1969dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
1970dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
19713b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        case FOURCC('h', 'd', 'l', 'r'):
19723b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        {
19730517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
19740517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1975ef185e94ce624146e3b1f3cbdb2404e833a0f81dChong Zhang            if (underQTMetaPath(mPath, 3)) {
1976ef185e94ce624146e3b1f3cbdb2404e833a0f81dChong Zhang                break;
1977ef185e94ce624146e3b1f3cbdb2404e833a0f81dChong Zhang            }
1978ef185e94ce624146e3b1f3cbdb2404e833a0f81dChong Zhang
19793b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t buffer;
19803b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (mDataSource->readAt(
19813b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                        data_offset + 8, &buffer, 4) < 4) {
19823b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_IO;
19833b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
19843b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
19853b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type = ntohl(buffer);
19863b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            // For the 3GPP file format, the handler-type within the 'hdlr' box
1987e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            // shall be 'text'. We also want to support 'sbtl' handler type
1988e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            // for a practical reason as various MPEG4 containers use it.
1989e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            if (type == FOURCC('t', 'e', 'x', 't') || type == FOURCC('s', 'b', 't', 'l')) {
1990cf75af8f76265fb2909028f5dc68c7029dbe5f49Lajos Molnar                if (mLastTrack != NULL) {
1991cf75af8f76265fb2909028f5dc68c7029dbe5f49Lajos Molnar                    mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
1992cf75af8f76265fb2909028f5dc68c7029dbe5f49Lajos Molnar                }
19933b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
19943b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
19953b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            break;
19963b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        }
19973b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
19988cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        case FOURCC('k', 'e', 'y', 's'):
19998cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        {
20008cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            *offset += chunk_size;
20018cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
20028cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            if (underQTMetaPath(mPath, 3)) {
20038cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                parseQTMetaKey(data_offset, chunk_data_size);
20048cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            }
20058cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            break;
20068cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        }
20078cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
2008c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        case FOURCC('t', 'r', 'e', 'x'):
2009c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        {
2010c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            *offset += chunk_size;
2011c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
2012c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (chunk_data_size < 24) {
2013c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_IO;
2014c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
2015c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            Trex trex;
2016c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (!mDataSource->getUInt32(data_offset + 4, &trex.track_ID) ||
2017c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                !mDataSource->getUInt32(data_offset + 8, &trex.default_sample_description_index) ||
2018c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                !mDataSource->getUInt32(data_offset + 12, &trex.default_sample_duration) ||
2019c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                !mDataSource->getUInt32(data_offset + 16, &trex.default_sample_size) ||
2020c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                !mDataSource->getUInt32(data_offset + 20, &trex.default_sample_flags)) {
2021c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_IO;
2022c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
2023c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            mTrex.add(trex);
2024c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            break;
2025c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        }
2026c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
20277a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        case FOURCC('t', 'x', '3', 'g'):
20287a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        {
2029f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
2030f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
2031f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
20323b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type;
20333b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            const void *data;
20343b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            size_t size = 0;
20353b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (!mLastTrack->meta->findData(
20363b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    kKeyTextFormatData, &type, &data, &size)) {
20373b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                size = 0;
20383b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
20393b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
20400e20b2093aa2bbc93afed8d68d3765d18a431b74Nick Kralevich            if ((chunk_size > SIZE_MAX) || (SIZE_MAX - chunk_size <= size)) {
2041dc69f4856187904bfb0d12a72cdf5a563a0deff2Joshua J. Drake                return ERROR_MALFORMED;
2042dc69f4856187904bfb0d12a72cdf5a563a0deff2Joshua J. Drake            }
2043dc69f4856187904bfb0d12a72cdf5a563a0deff2Joshua J. Drake
20448da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            uint8_t *buffer = new (std::nothrow) uint8_t[size + chunk_size];
20458da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            if (buffer == NULL) {
20468da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen                return ERROR_MALFORMED;
20478da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            }
20483b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
20493b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (size > 0) {
20503b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                memcpy(buffer, data, size);
20513b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
20523b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
20533b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size))
20543b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    < chunk_size) {
20553b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                delete[] buffer;
20563b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                buffer = NULL;
20573b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
20580517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen                // advance read pointer so we don't end up reading this again
20590517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen                *offset += chunk_size;
20603b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_IO;
20613b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
20623b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
20633b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            mLastTrack->meta->setData(
20643b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    kKeyTextFormatData, 0, buffer, size + chunk_size);
20653b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
20663b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            delete[] buffer;
20677a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
20687a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            *offset += chunk_size;
20697a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            break;
20707a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        }
20717a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
2072515e855eae78aa495da58356486aaa666cb57fd1James Dong        case FOURCC('c', 'o', 'v', 'r'):
2073515e855eae78aa495da58356486aaa666cb57fd1James Dong        {
20740517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
20750517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
2076515e855eae78aa495da58356486aaa666cb57fd1James Dong            if (mFileMetaData != NULL) {
2077635bc8f90429b2fdcaf7f8d43f7f59bcd0fe951cDan Albert                ALOGV("chunk_data_size = %" PRId64 " and data_offset = %" PRId64,
2078635bc8f90429b2fdcaf7f8d43f7f59bcd0fe951cDan Albert                      chunk_data_size, data_offset);
20791e51401794ff830c912c21123c321b83c17b491dJoshua J. Drake
2080635bc8f90429b2fdcaf7f8d43f7f59bcd0fe951cDan Albert                if (chunk_data_size < 0 || static_cast<uint64_t>(chunk_data_size) >= SIZE_MAX - 1) {
20811e51401794ff830c912c21123c321b83c17b491dJoshua J. Drake                    return ERROR_MALFORMED;
20821e51401794ff830c912c21123c321b83c17b491dJoshua J. Drake                }
20831552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1);
2084515e855eae78aa495da58356486aaa666cb57fd1James Dong                if (mDataSource->readAt(
20851552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                    data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) {
2086515e855eae78aa495da58356486aaa666cb57fd1James Dong                    return ERROR_IO;
2087515e855eae78aa495da58356486aaa666cb57fd1James Dong                }
2088515e855eae78aa495da58356486aaa666cb57fd1James Dong                const int kSkipBytesOfDataBox = 16;
208997d45dbfdfc9018f1cbf72641c1447ff59431ae3Joshua J. Drake                if (chunk_data_size <= kSkipBytesOfDataBox) {
209097d45dbfdfc9018f1cbf72641c1447ff59431ae3Joshua J. Drake                    return ERROR_MALFORMED;
209197d45dbfdfc9018f1cbf72641c1447ff59431ae3Joshua J. Drake                }
209297d45dbfdfc9018f1cbf72641c1447ff59431ae3Joshua J. Drake
2093515e855eae78aa495da58356486aaa666cb57fd1James Dong                mFileMetaData->setData(
2094515e855eae78aa495da58356486aaa666cb57fd1James Dong                    kKeyAlbumArt, MetaData::TYPE_NONE,
20951552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                    buffer->data() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox);
2096515e855eae78aa495da58356486aaa666cb57fd1James Dong            }
2097515e855eae78aa495da58356486aaa666cb57fd1James Dong
2098515e855eae78aa495da58356486aaa666cb57fd1James Dong            break;
2099515e855eae78aa495da58356486aaa666cb57fd1James Dong        }
2100515e855eae78aa495da58356486aaa666cb57fd1James Dong
210158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        case FOURCC('c', 'o', 'l', 'r'):
210258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        {
210358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            *offset += chunk_size;
210458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            // this must be in a VisualSampleEntry box under the Sample Description Box ('stsd')
210558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            // ignore otherwise
210658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            if (depth >= 2 && mPath[depth - 2] == FOURCC('s', 't', 's', 'd')) {
210758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar                status_t err = parseColorInfo(data_offset, chunk_data_size);
210858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar                if (err != OK) {
210958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar                    return err;
211058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar                }
211158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            }
211258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
211358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            break;
211458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        }
211558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
2116fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('t', 'i', 't', 'l'):
2117fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('p', 'e', 'r', 'f'):
2118fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'u', 't', 'h'):
2119fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('g', 'n', 'r', 'e'):
2120fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'l', 'b', 'm'):
2121fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('y', 'r', 'r', 'c'):
2122fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
21230517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
21240517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
2125fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            status_t err = parse3GPPMetaData(data_offset, chunk_data_size, depth);
2126fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2127fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (err != OK) {
2128fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                return err;
2129fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2130fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2131fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2132fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2133fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2134328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        case FOURCC('I', 'D', '3', '2'):
2135328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        {
21360517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
21370517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
2138328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            if (chunk_data_size < 6) {
2139328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                return ERROR_MALFORMED;
2140328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            }
2141328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2142328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            parseID3v2MetaData(data_offset + 6);
2143328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2144328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            break;
2145328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        }
2146328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
21475d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('-', '-', '-', '-'):
21485d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        {
21495d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentMean.clear();
21505d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentName.clear();
21515d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentData.clear();
21525d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            *offset += chunk_size;
21535d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            break;
21545d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        }
21555d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen
215605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('s', 'i', 'd', 'x'):
215705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        {
215805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            parseSegmentIndex(data_offset, chunk_data_size);
215905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset += chunk_size;
216005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return UNKNOWN_ERROR; // stop parsing after sidx
216105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
216205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2163bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa        case FOURCC('a', 'c', '-', '3'):
2164bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa        {
2165bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa            *offset += chunk_size;
2166bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa            return parseAC3SampleEntry(data_offset);
2167bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa        }
2168bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa
216920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
217020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
21718cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            // check if we're parsing 'ilst' for meta keys
21728cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            // if so, treat type as a number (key-id).
21738cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            if (underQTMetaPath(mPath, 3)) {
21748cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                parseQTMetaVal(chunk_type, data_offset, chunk_data_size);
21758cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            }
21768cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
217720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
217820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
217920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
218020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
218120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
218220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
218320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
218420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2185bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasastatus_t MPEG4Extractor::parseAC3SampleEntry(off64_t offset) {
2186bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    // skip 16 bytes:
2187bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    //  + 6-byte reserved,
2188bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    //  + 2-byte data reference index,
2189bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    //  + 8-byte reserved
2190bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    offset += 16;
2191bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    uint16_t channelCount;
2192bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    if (!mDataSource->getUInt16(offset, &channelCount)) {
2193bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa        return ERROR_MALFORMED;
2194bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    }
2195bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    // skip 8 bytes:
2196bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    //  + 2-byte channelCount,
2197bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    //  + 2-byte sample size,
2198bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    //  + 4-byte reserved
2199bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    offset += 8;
2200bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    uint16_t sampleRate;
2201bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    if (!mDataSource->getUInt16(offset, &sampleRate)) {
2202bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa        ALOGE("MPEG4Extractor: error while reading ac-3 block: cannot read sample rate");
2203bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa        return ERROR_MALFORMED;
2204bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    }
2205bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa
2206bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    // skip 4 bytes:
2207bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    //  + 2-byte sampleRate,
2208bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    //  + 2-byte reserved
2209bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    offset += 4;
2210bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    return parseAC3SpecificBox(offset, sampleRate);
2211bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa}
2212bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa
2213bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasastatus_t MPEG4Extractor::parseAC3SpecificBox(
2214bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa        off64_t offset, uint16_t sampleRate) {
2215bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    uint32_t size;
2216bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    // + 4-byte size
2217bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    // + 4-byte type
2218bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    // + 3-byte payload
2219bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    const uint32_t kAC3SpecificBoxSize = 11;
2220bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    if (!mDataSource->getUInt32(offset, &size) || size < kAC3SpecificBoxSize) {
2221bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa        ALOGE("MPEG4Extractor: error while reading ac-3 block: cannot read specific box size");
2222bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa        return ERROR_MALFORMED;
2223bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    }
2224bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa
2225bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    offset += 4;
2226bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    uint32_t type;
2227bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    if (!mDataSource->getUInt32(offset, &type) || type != FOURCC('d', 'a', 'c', '3')) {
2228bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa        ALOGE("MPEG4Extractor: error while reading ac-3 specific block: header not dac3");
2229bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa        return ERROR_MALFORMED;
2230bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    }
2231bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa
2232bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    offset += 4;
2233bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    const uint32_t kAC3SpecificBoxPayloadSize = 3;
2234bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    uint8_t chunk[kAC3SpecificBoxPayloadSize];
2235bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    if (mDataSource->readAt(offset, chunk, sizeof(chunk)) != sizeof(chunk)) {
2236bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa        ALOGE("MPEG4Extractor: error while reading ac-3 specific block: bitstream fields");
2237bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa        return ERROR_MALFORMED;
2238bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    }
2239bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa
2240bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    ABitReader br(chunk, sizeof(chunk));
2241bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    static const unsigned channelCountTable[] = {2, 1, 2, 3, 3, 4, 4, 5};
2242bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    static const unsigned sampleRateTable[] = {48000, 44100, 32000};
2243bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa
2244bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    unsigned fscod = br.getBits(2);
2245bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    if (fscod == 3) {
2246bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa        ALOGE("Incorrect fscod (3) in AC3 header");
2247bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa        return ERROR_MALFORMED;
2248bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    }
2249bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    unsigned boxSampleRate = sampleRateTable[fscod];
2250bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    if (boxSampleRate != sampleRate) {
2251bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa        ALOGE("sample rate mismatch: boxSampleRate = %d, sampleRate = %d",
2252bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa            boxSampleRate, sampleRate);
2253bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa        return ERROR_MALFORMED;
2254bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    }
2255bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa
2256bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    unsigned bsid = br.getBits(5);
2257bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    if (bsid > 8) {
2258bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa        ALOGW("Incorrect bsid in AC3 header. Possibly E-AC-3?");
2259bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa        return ERROR_MALFORMED;
2260bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    }
2261bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa
2262bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    // skip
2263bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    unsigned bsmod __unused = br.getBits(3);
2264bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa
2265bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    unsigned acmod = br.getBits(3);
2266bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    unsigned lfeon = br.getBits(1);
2267bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    unsigned channelCount = channelCountTable[acmod] + lfeon;
2268bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa
2269bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    if (mLastTrack == NULL) {
2270bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa        return ERROR_MALFORMED;
2271bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    }
2272bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AC3);
2273bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    mLastTrack->meta->setInt32(kKeyChannelCount, channelCount);
2274bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
2275bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa    return OK;
2276bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa}
2277bcbd7bce03772a22c2965dab636c1f67b7a655f5Pawin Vongmasa
227805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) {
227905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen  ALOGV("MPEG4Extractor::parseSegmentIndex");
228005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
228105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 12) {
228205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      return -EINVAL;
228305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
228405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
228505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
228605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) {
228705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
228805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
228905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
229005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t version = flags >> 24;
229105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    flags &= 0xffffff;
229205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
229305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx version %d", version);
229405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
229505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t referenceId;
229605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, &referenceId)) {
229705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
229805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
229905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
230005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t timeScale;
230105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 8, &timeScale)) {
230205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
230305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
230405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx refid/timescale: %d/%d", referenceId, timeScale);
2305e3e82d54c51a3130badcd9e433fe808d965f15c2Joshua J. Drake    if (timeScale == 0)
2306e3e82d54c51a3130badcd9e433fe808d965f15c2Joshua J. Drake        return ERROR_MALFORMED;
230705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
230805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t earliestPresentationTime;
230905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t firstOffset;
231005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
231105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 12;
231205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 12;
231305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
231405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (version == 0) {
231505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 8) {
231605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
231705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
231805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t tmp;
231905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
232005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
232105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
232205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        earliestPresentationTime = tmp;
232305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset + 4, &tmp)) {
232405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
232505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
232605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        firstOffset = tmp;
232705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 8;
232805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 8;
232905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
233005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 16) {
233105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
233205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
233305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset, &earliestPresentationTime)) {
233405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
233505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
233605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset + 8, &firstOffset)) {
233705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
233805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
233905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 16;
234005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 16;
234105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
2342a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("sidx pres/off: %" PRIu64 "/%" PRIu64, earliestPresentationTime, firstOffset);
234305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
234405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 4) {
234505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
234605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
234705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
234805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint16_t referenceCount;
234905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt16(offset + 2, &referenceCount)) {
235005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
235105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
235205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 4;
235305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 4;
235405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("refcount: %d", referenceCount);
235505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
235605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < referenceCount * 12) {
235705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
235805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
235905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
236005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t total_duration = 0;
236105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    for (unsigned int i = 0; i < referenceCount; i++) {
236205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t d1, d2, d3;
236305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
236405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &d1) ||     // size
236505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            !mDataSource->getUInt32(offset + 4, &d2) || // duration
236605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            !mDataSource->getUInt32(offset + 8, &d3)) { // flags
236705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
236805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
236905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
237005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (d1 & 0x80000000) {
237105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGW("sub-sidx boxes not supported yet");
237205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
237305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool sap = d3 & 0x80000000;
23743f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen        uint32_t saptype = (d3 >> 28) & 7;
23753f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen        if (!sap || (saptype != 1 && saptype != 2)) {
23763f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            // type 1 and 2 are sync samples
23773f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            ALOGW("not a stream access point, or unsupported type: %08x", d3);
237805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
237905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        total_duration += d2;
238005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 12;
238105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV(" item %d, %08x %08x %08x", i, d1, d2, d3);
238205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        SidxEntry se;
238305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        se.mSize = d1 & 0x7fffffff;
238405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        se.mDurationUs = 1000000LL * d2 / timeScale;
238505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mSidxEntries.add(se);
238605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
238705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2388c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    uint64_t sidxDuration = total_duration * 1000000 / timeScale;
238905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2390f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake    if (mLastTrack == NULL)
2391f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake        return ERROR_MALFORMED;
2392f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
239305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t metaDuration;
239405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mLastTrack->meta->findInt64(kKeyDuration, &metaDuration) || metaDuration == 0) {
2395c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        mLastTrack->meta->setInt64(kKeyDuration, sidxDuration);
239605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
239705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
239805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
239905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
24008cfad968d5ec429b033caff9743f1ef15090be61Chong Zhangstatus_t MPEG4Extractor::parseQTMetaKey(off64_t offset, size_t size) {
24018cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (size < 8) {
24028cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        return ERROR_MALFORMED;
24038cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
24048cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
24058cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    uint32_t count;
24068cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (!mDataSource->getUInt32(offset + 4, &count)) {
24078cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        return ERROR_MALFORMED;
24088cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
24098cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
24108cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (mMetaKeyMap.size() > 0) {
24118cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        ALOGW("'keys' atom seen again, discarding existing entries");
24128cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        mMetaKeyMap.clear();
24138cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
24148cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
24158cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    off64_t keyOffset = offset + 8;
24168cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    off64_t stopOffset = offset + size;
24178cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    for (size_t i = 1; i <= count; i++) {
24188cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        if (keyOffset + 8 > stopOffset) {
24198cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            return ERROR_MALFORMED;
24208cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        }
24218cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
24228cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        uint32_t keySize;
24238cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        if (!mDataSource->getUInt32(keyOffset, &keySize)
24248cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                || keySize < 8
24258cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                || keyOffset + keySize > stopOffset) {
24268cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            return ERROR_MALFORMED;
24278cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        }
24288cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
24298cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        uint32_t type;
24308cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        if (!mDataSource->getUInt32(keyOffset + 4, &type)
24318cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                || type != FOURCC('m', 'd', 't', 'a')) {
24328cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            return ERROR_MALFORMED;
24338cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        }
24348cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
24358cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        keySize -= 8;
24368cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        keyOffset += 8;
24378cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
24388cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        sp<ABuffer> keyData = new ABuffer(keySize);
24398cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        if (keyData->data() == NULL) {
24408cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            return ERROR_MALFORMED;
24418cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        }
24428cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        if (mDataSource->readAt(
24438cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                keyOffset, keyData->data(), keySize) < (ssize_t) keySize) {
24448cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            return ERROR_MALFORMED;
24458cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        }
24468cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
24478cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        AString key((const char *)keyData->data(), keySize);
24488cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        mMetaKeyMap.add(i, key);
24498cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
24508cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        keyOffset += keySize;
24518cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
24528cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    return OK;
24538cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang}
24548cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
24558cfad968d5ec429b033caff9743f1ef15090be61Chong Zhangstatus_t MPEG4Extractor::parseQTMetaVal(
24568cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        int32_t keyId, off64_t offset, size_t size) {
24578cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    ssize_t index = mMetaKeyMap.indexOfKey(keyId);
24588cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (index < 0) {
24598cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        // corresponding key is not present, ignore
24608cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        return ERROR_MALFORMED;
24618cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
246205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
24638cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (size <= 16) {
24648cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        return ERROR_MALFORMED;
24658cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
24668cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    uint32_t dataSize;
24678cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (!mDataSource->getUInt32(offset, &dataSize)
24688cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            || dataSize > size || dataSize <= 16) {
24698cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        return ERROR_MALFORMED;
24708cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
24718cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    uint32_t atomFourCC;
24728cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (!mDataSource->getUInt32(offset + 4, &atomFourCC)
24738cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            || atomFourCC != FOURCC('d', 'a', 't', 'a')) {
24748cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        return ERROR_MALFORMED;
24758cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
24768cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    uint32_t dataType;
24778cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (!mDataSource->getUInt32(offset + 8, &dataType)
24788cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            || ((dataType & 0xff000000) != 0)) {
24798cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        // not well-known type
24808cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        return ERROR_MALFORMED;
24818cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
24828cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
24838cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    dataSize -= 16;
24848cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    offset += 16;
24858cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
24868cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (dataType == 23 && dataSize >= 4) {
24878cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        // BE Float32
24888cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        uint32_t val;
24898cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        if (!mDataSource->getUInt32(offset, &val)) {
24908cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            return ERROR_MALFORMED;
24918cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        }
24928cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        if (!strcasecmp(mMetaKeyMap[index].c_str(), "com.android.capture.fps")) {
24938cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            mFileMetaData->setFloat(kKeyCaptureFramerate, *(float *)&val);
24948cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        }
24958cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    } else {
24968cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        // add more keys if needed
24978cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        ALOGV("ignoring key: type %d, size %d", dataType, dataSize);
24988cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
24998cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
25008cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    return OK;
25018cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang}
250205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2503ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huberstatus_t MPEG4Extractor::parseTrackHeader(
2504c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t data_offset, off64_t data_size) {
2505ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (data_size < 4) {
2506ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_MALFORMED;
2507ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2508ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2509ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint8_t version;
2510ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (mDataSource->readAt(data_offset, &version, 1) < 1) {
2511ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_IO;
2512ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2513ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2514ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    size_t dynSize = (version == 1) ? 36 : 24;
2515ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2516ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint8_t buffer[36 + 60];
2517ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2518c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    if (data_size != (off64_t)dynSize + 60) {
2519ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_MALFORMED;
2520ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2521ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2522ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (mDataSource->readAt(
2523ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber                data_offset, buffer, data_size) < (ssize_t)data_size) {
2524ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_IO;
2525ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2526ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2527b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    uint64_t ctime __unused, mtime __unused, duration __unused;
2528ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t id;
2529ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2530ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (version == 1) {
2531ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        ctime = U64_AT(&buffer[4]);
2532ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mtime = U64_AT(&buffer[12]);
2533ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        id = U32_AT(&buffer[20]);
2534ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        duration = U64_AT(&buffer[28]);
253504022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen    } else if (version == 0) {
2536ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        ctime = U32_AT(&buffer[4]);
2537ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mtime = U32_AT(&buffer[8]);
2538ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        id = U32_AT(&buffer[12]);
2539ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        duration = U32_AT(&buffer[20]);
254004022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen    } else {
254104022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen        return ERROR_UNSUPPORTED;
2542ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2543ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2544f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake    if (mLastTrack == NULL)
2545f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake        return ERROR_MALFORMED;
2546f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
2547ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    mLastTrack->meta->setInt32(kKeyTrackID, id);
2548ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2549ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    size_t matrixOffset = dynSize + 16;
2550ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a00 = U32_AT(&buffer[matrixOffset]);
2551ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a01 = U32_AT(&buffer[matrixOffset + 4]);
2552ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a10 = U32_AT(&buffer[matrixOffset + 12]);
2553ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a11 = U32_AT(&buffer[matrixOffset + 16]);
2554ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2555ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#if 0
2556b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    int32_t dx = U32_AT(&buffer[matrixOffset + 8]);
2557b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    int32_t dy = U32_AT(&buffer[matrixOffset + 20]);
2558b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe
2559df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("x' = %.2f * x + %.2f * y + %.2f",
2560ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber         a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f);
2561df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("y' = %.2f * x + %.2f * y + %.2f",
2562ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber         a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f);
2563ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#endif
2564ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2565ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t rotationDegrees;
2566ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2567ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    static const int32_t kFixedOne = 0x10000;
2568ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) {
2569ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        // Identity, no rotation
2570ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 0;
2571ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) {
2572ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 90;
2573ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) {
2574ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 270;
2575ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) {
2576ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 180;
2577ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else {
25785ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("We only support 0,90,180,270 degree rotation matrices");
2579ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 0;
2580ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2581ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2582ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (rotationDegrees != 0) {
2583ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees);
2584ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2585ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2586b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    // Handle presentation display size, which could be different
2587b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    // from the image size indicated by kKeyWidth and kKeyHeight.
2588ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t width = U32_AT(&buffer[dynSize + 52]);
2589ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t height = U32_AT(&buffer[dynSize + 56]);
2590b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    mLastTrack->meta->setInt32(kKeyDisplayWidth, width >> 16);
2591b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    mLastTrack->meta->setInt32(kKeyDisplayHeight, height >> 16);
2592ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2593ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    return OK;
2594ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber}
2595ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2596fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhéstatus_t MPEG4Extractor::parseITunesMetaData(off64_t offset, size_t size) {
2597c570778430a22b5488cae72982cf9fb8033dbda3Nick Kralevich    if (size < 4 || size == SIZE_MAX) {
259872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_MALFORMED;
259972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
260072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
26018da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    uint8_t *buffer = new (std::nothrow) uint8_t[size + 1];
26028da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    if (buffer == NULL) {
26038da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        return ERROR_MALFORMED;
26048da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    }
260572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (mDataSource->readAt(
260672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                offset, buffer, size) != (ssize_t)size) {
260772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        delete[] buffer;
260872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        buffer = NULL;
260972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
261072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_IO;
261172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
261272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
261372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t flags = U32_AT(buffer);
261472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
261572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t metadataKey = 0;
26165d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    char chunk[5];
26175d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    MakeFourCCString(mPath[4], chunk);
2618ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar    ALOGV("meta: %s @ %lld", chunk, (long long)offset);
26192d0ac425564ff9882ebaac5267d1a04d4af67d00Bernhard Rosenkränzer    switch ((int32_t)mPath[4]) {
262072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'a', 'l', 'b'):
262172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
262272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbum;
262372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
262472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
262572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'A', 'R', 'T'):
262672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
262772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyArtist;
262872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
262972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
263066ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        case FOURCC('a', 'A', 'R', 'T'):
263166ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        {
263266ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            metadataKey = kKeyAlbumArtist;
263366ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            break;
263466ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        }
263572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'd', 'a', 'y'):
263672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
263772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyYear;
263872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
263972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
264072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'n', 'a', 'm'):
264172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
264272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyTitle;
264372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
264472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
264572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'w', 'r', 't'):
264672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
264772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyWriter;
264872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
264972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
265072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('c', 'o', 'v', 'r'):
265172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
265272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbumArt;
265372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
265472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
265572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('g', 'n', 'r', 'e'):
265672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
265772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyGenre;
265872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
265972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
266026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC(0xa9, 'g', 'e', 'n'):
266126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
266226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            metadataKey = kKeyGenre;
266326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
266426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
266511f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        case FOURCC('c', 'p', 'i', 'l'):
266611f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        {
266711f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            if (size == 9 && flags == 21) {
266811f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                char tmp[16];
266911f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                sprintf(tmp, "%d",
267011f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                        (int)buffer[size - 1]);
267111f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen
267211f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                mFileMetaData->setCString(kKeyCompilation, tmp);
267311f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            }
267411f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            break;
267511f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        }
267672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('t', 'r', 'k', 'n'):
267772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
267872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (size == 16 && flags == 0) {
267972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char tmp[16];
2680afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTrack = (uint16_t*)&buffer[10];
2681afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTotalTracks = (uint16_t*)&buffer[12];
2682afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                sprintf(tmp, "%d/%d", ntohs(*pTrack), ntohs(*pTotalTracks));
268372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
268472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
268572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
268672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
268772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
268826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC('d', 'i', 's', 'k'):
268926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
2690afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik            if ((size == 14 || size == 16) && flags == 0) {
269126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                char tmp[16];
2692afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pDisc = (uint16_t*)&buffer[10];
2693afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTotalDiscs = (uint16_t*)&buffer[12];
2694afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                sprintf(tmp, "%d/%d", ntohs(*pDisc), ntohs(*pTotalDiscs));
269526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
269626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(kKeyDiscNumber, tmp);
269726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            }
269826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
269926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
27005d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('-', '-', '-', '-'):
27015d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        {
27025d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            buffer[size] = '\0';
27035d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            switch (mPath[5]) {
27045d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('m', 'e', 'a', 'n'):
27055d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentMean.setTo((const char *)buffer + 4);
27065d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
27075d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('n', 'a', 'm', 'e'):
27085d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentName.setTo((const char *)buffer + 4);
27095d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
27105d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('d', 'a', 't', 'a'):
27115cae16bdce77b0a3ba590b55637f7d55a2f35402Wei Jia                    if (size < 8) {
27125cae16bdce77b0a3ba590b55637f7d55a2f35402Wei Jia                        delete[] buffer;
27135cae16bdce77b0a3ba590b55637f7d55a2f35402Wei Jia                        buffer = NULL;
27145cae16bdce77b0a3ba590b55637f7d55a2f35402Wei Jia                        ALOGE("b/24346430");
27155cae16bdce77b0a3ba590b55637f7d55a2f35402Wei Jia                        return ERROR_MALFORMED;
27165cae16bdce77b0a3ba590b55637f7d55a2f35402Wei Jia                    }
27175d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentData.setTo((const char *)buffer + 8);
27185d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
27195d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            }
27208c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
27218c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // Once we have a set of mean/name/data info, go ahead and process
27228c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // it to see if its something we are interested in.  Whether or not
27238c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // were are interested in the specific tag, make sure to clear out
27248c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // the set so we can be ready to process another tuple should one
27258c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // show up later in the file.
27268c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            if ((mLastCommentMean.length() != 0) &&
27278c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                (mLastCommentName.length() != 0) &&
27288c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                (mLastCommentData.length() != 0)) {
27298c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
27308c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                if (mLastCommentMean == "com.apple.iTunes"
27318c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        && mLastCommentName == "iTunSMPB") {
27328c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    int32_t delay, padding;
27338c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    if (sscanf(mLastCommentData,
27348c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                               " %*x %x %x %*x", &delay, &padding) == 2) {
2735f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                        if (mLastTrack == NULL)
2736f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                            return ERROR_MALFORMED;
2737f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
27388c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
27398c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        mLastTrack->meta->setInt32(kKeyEncoderPadding, padding);
27408c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    }
27415d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                }
27428c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
27435d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentMean.clear();
27445d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentName.clear();
27455d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentData.clear();
27465d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            }
27475d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            break;
27485d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        }
274926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
275072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        default:
275172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
275272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
275372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
2754328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    if (size >= 8 && metadataKey && !mFileMetaData->hasData(metadataKey)) {
275572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        if (metadataKey == kKeyAlbumArt) {
275672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setData(
275772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    kKeyAlbumArt, MetaData::TYPE_NONE,
275872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    buffer + 8, size - 8);
275972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else if (metadataKey == kKeyGenre) {
276072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (flags == 0) {
276126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // uint8_t genre code, iTunes genre codes are
276226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // the standard id3 codes, except they start
276326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // at 1 instead of 0 (e.g. Pop is 14, not 13)
276426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // We use standard id3 numbering, so subtract 1.
276526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                int genrecode = (int)buffer[size - 1];
276626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                genrecode--;
276726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                if (genrecode < 0) {
276826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                    genrecode = 255; // reserved for 'unknown genre'
276926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                }
277072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char genre[10];
277126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                sprintf(genre, "%d", genrecode);
277272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
277372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(metadataKey, genre);
277426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            } else if (flags == 1) {
277526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // custom genre string
277626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                buffer[size] = '\0';
277726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
277826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(
277926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                        metadataKey, (const char *)buffer + 8);
278072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
278172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else {
278272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            buffer[size] = '\0';
278372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
278472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(
278572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    metadataKey, (const char *)buffer + 8);
278672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
278772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
278872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
278972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    delete[] buffer;
279072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    buffer = NULL;
279172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
279272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return OK;
279372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
279472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
279558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnarstatus_t MPEG4Extractor::parseColorInfo(off64_t offset, size_t size) {
279658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    if (size < 4 || size == SIZE_MAX || mLastTrack == NULL) {
279758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        return ERROR_MALFORMED;
279858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    }
279958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
280058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    uint8_t *buffer = new (std::nothrow) uint8_t[size + 1];
280158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    if (buffer == NULL) {
280258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        return ERROR_MALFORMED;
280358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    }
280458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    if (mDataSource->readAt(offset, buffer, size) != (ssize_t)size) {
280558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        delete[] buffer;
280658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        buffer = NULL;
280758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
280858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        return ERROR_IO;
280958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    }
281058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
281158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    int32_t type = U32_AT(&buffer[0]);
281258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    if ((type == FOURCC('n', 'c', 'l', 'x') && size >= 11)
281358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            || (type == FOURCC('n', 'c', 'l', 'c' && size >= 10))) {
281458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        int32_t primaries = U16_AT(&buffer[4]);
281558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        int32_t transfer = U16_AT(&buffer[6]);
281658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        int32_t coeffs = U16_AT(&buffer[8]);
281758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        bool fullRange = (type == FOURCC('n', 'c', 'l', 'x')) && (buffer[10] & 128);
281858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
281958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        ColorAspects aspects;
282058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        ColorUtils::convertIsoColorAspectsToCodecAspects(
282158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar                primaries, transfer, coeffs, fullRange, aspects);
282258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
282358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        // only store the first color specification
282458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        if (!mLastTrack->meta->hasData(kKeyColorPrimaries)) {
282558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            mLastTrack->meta->setInt32(kKeyColorPrimaries, aspects.mPrimaries);
282658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            mLastTrack->meta->setInt32(kKeyTransferFunction, aspects.mTransfer);
282758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            mLastTrack->meta->setInt32(kKeyColorMatrix, aspects.mMatrixCoeffs);
282858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            mLastTrack->meta->setInt32(kKeyColorRange, aspects.mRange);
282958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        }
283058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    }
283158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
283258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    delete[] buffer;
283358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    buffer = NULL;
283458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
283558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    return OK;
283658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar}
283758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
2838fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhéstatus_t MPEG4Extractor::parse3GPPMetaData(off64_t offset, size_t size, int depth) {
28395cea0155cfc41f67e91343c342f44251c03fde3aJoshua J. Drake    if (size < 4 || size == SIZE_MAX) {
2840fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        return ERROR_MALFORMED;
2841fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2842fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
28435cea0155cfc41f67e91343c342f44251c03fde3aJoshua J. Drake    uint8_t *buffer = new (std::nothrow) uint8_t[size + 1];
28448da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    if (buffer == NULL) {
28458da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        return ERROR_MALFORMED;
28468da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    }
2847fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    if (mDataSource->readAt(
2848fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                offset, buffer, size) != (ssize_t)size) {
2849fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        delete[] buffer;
2850fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        buffer = NULL;
2851fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2852fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        return ERROR_IO;
2853fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2854fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2855fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    uint32_t metadataKey = 0;
2856fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    switch (mPath[depth]) {
2857fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('t', 'i', 't', 'l'):
2858fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2859fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyTitle;
2860fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2861fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2862fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('p', 'e', 'r', 'f'):
2863fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2864fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyArtist;
2865fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2866fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2867fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'u', 't', 'h'):
2868fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2869fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyWriter;
2870fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2871fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2872fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('g', 'n', 'r', 'e'):
2873fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2874fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyGenre;
2875fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2876fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2877fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'l', 'b', 'm'):
2878fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2879fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (buffer[size - 1] != '\0') {
2880fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé              char tmp[4];
2881fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé              sprintf(tmp, "%u", buffer[size - 1]);
2882fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2883fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé              mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
2884fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2885fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2886fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyAlbum;
2887fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2888fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2889fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('y', 'r', 'r', 'c'):
2890fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2891fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            char tmp[5];
2892fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            uint16_t year = U16_AT(&buffer[4]);
2893fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2894fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (year < 10000) {
2895fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                sprintf(tmp, "%u", year);
2896fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2897fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                mFileMetaData->setCString(kKeyYear, tmp);
2898fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2899fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2900fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2901fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2902fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        default:
2903fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2904fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2905fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2906fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    if (metadataKey > 0) {
2907fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        bool isUTF8 = true; // Common case
2908fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        char16_t *framedata = NULL;
2909fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        int len16 = 0; // Number of UTF-16 characters
2910fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2911fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        // smallest possible valid UTF-16 string w BOM: 0xfe 0xff 0x00 0x00
29129458e715d391ee8fe455fc31f07ff35ce12e0531Joshua J. Drake        if (size < 6) {
29139458e715d391ee8fe455fc31f07ff35ce12e0531Joshua J. Drake            return ERROR_MALFORMED;
29149458e715d391ee8fe455fc31f07ff35ce12e0531Joshua J. Drake        }
29159458e715d391ee8fe455fc31f07ff35ce12e0531Joshua J. Drake
2916fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        if (size - 6 >= 4) {
2917fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            len16 = ((size - 6) / 2) - 1; // don't include 0x0000 terminator
2918fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            framedata = (char16_t *)(buffer + 6);
2919fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (0xfffe == *framedata) {
2920fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                // endianness marker (BOM) doesn't match host endianness
2921fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                for (int i = 0; i < len16; i++) {
2922fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                    framedata[i] = bswap_16(framedata[i]);
2923fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                }
2924fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                // BOM is now swapped to 0xfeff, we will execute next block too
2925fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2926fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2927fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (0xfeff == *framedata) {
2928fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                // Remove the BOM
2929fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                framedata++;
2930fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                len16--;
2931fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                isUTF8 = false;
2932fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2933fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // else normal non-zero-length UTF-8 string
2934fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // we can't handle UTF-16 without BOM as there is no other
2935fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // indication of encoding.
2936fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2937fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2938fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        if (isUTF8) {
29395cea0155cfc41f67e91343c342f44251c03fde3aJoshua J. Drake            buffer[size] = 0;
2940fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            mFileMetaData->setCString(metadataKey, (const char *)buffer + 6);
2941fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        } else {
2942fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // Convert from UTF-16 string to UTF-8 string.
2943fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            String8 tmpUTF8str(framedata, len16);
2944fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            mFileMetaData->setCString(metadataKey, tmpUTF8str.string());
2945fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2946fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2947fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2948fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    delete[] buffer;
2949fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    buffer = NULL;
2950fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2951fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    return OK;
2952fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé}
2953fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2954328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhévoid MPEG4Extractor::parseID3v2MetaData(off64_t offset) {
2955328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    ID3 id3(mDataSource, true /* ignorev1 */, offset);
2956328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2957328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    if (id3.isValid()) {
2958328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        struct Map {
2959328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            int key;
2960328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            const char *tag1;
2961328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            const char *tag2;
2962328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        };
2963328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        static const Map kMap[] = {
2964328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyAlbum, "TALB", "TAL" },
2965328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyArtist, "TPE1", "TP1" },
2966328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyAlbumArtist, "TPE2", "TP2" },
2967328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyComposer, "TCOM", "TCM" },
2968328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyGenre, "TCON", "TCO" },
2969328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyTitle, "TIT2", "TT2" },
2970328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyYear, "TYE", "TYER" },
2971328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyAuthor, "TXT", "TEXT" },
2972328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyCDTrackNumber, "TRK", "TRCK" },
2973328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyDiscNumber, "TPA", "TPOS" },
2974328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyCompilation, "TCP", "TCMP" },
2975328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        };
2976328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
2977328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2978328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        for (size_t i = 0; i < kNumMapEntries; ++i) {
2979328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            if (!mFileMetaData->hasData(kMap[i].key)) {
2980328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                ID3::Iterator *it = new ID3::Iterator(id3, kMap[i].tag1);
2981328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                if (it->done()) {
2982328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    delete it;
2983328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    it = new ID3::Iterator(id3, kMap[i].tag2);
2984328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                }
2985328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2986328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                if (it->done()) {
2987328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    delete it;
2988328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    continue;
2989328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                }
2990328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2991328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                String8 s;
2992328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                it->getString(&s);
2993328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                delete it;
2994328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2995328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                mFileMetaData->setCString(kMap[i].key, s);
2996328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            }
2997328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        }
2998328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2999328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        size_t dataSize;
3000328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        String8 mime;
3001328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        const void *data = id3.getAlbumArt(&dataSize, &mime);
3002328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
3003328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        if (data) {
3004328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            mFileMetaData->setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize);
3005328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            mFileMetaData->setCString(kKeyAlbumArtMIME, mime.string());
3006328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        }
3007328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    }
3008328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé}
3009328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
3010b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissensp<IMediaSource> MPEG4Extractor::getTrack(size_t index) {
301120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
301220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
3013693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return NULL;
301420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
301520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
301620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
301720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
301820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
3019693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber            return NULL;
302020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
302120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
302220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
302320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
302420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
302520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3026371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
3027371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
3028371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
3029371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
3030c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
3031c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    Trex *trex = NULL;
3032c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    int32_t trackId;
3033c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    if (track->meta->findInt32(kKeyTrackID, &trackId)) {
3034c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        for (size_t i = 0; i < mTrex.size(); i++) {
3035c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            Trex *t = &mTrex.editItemAt(index);
3036c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (t->track_ID == (uint32_t) trackId) {
3037c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                trex = t;
3038c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                break;
3039c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
3040c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        }
30410386c91b8a910a134e5898ffa924c1b6c7560b13Wei Jia    } else {
30420386c91b8a910a134e5898ffa924c1b6c7560b13Wei Jia        ALOGE("b/21657957");
30430386c91b8a910a134e5898ffa924c1b6c7560b13Wei Jia        return NULL;
3044c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    }
3045c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
3046a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("getTrack called, pssh: %zu", mPssh.size());
3047ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3048a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia    const char *mime;
3049a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia    if (!track->meta->findCString(kKeyMIMEType, &mime)) {
3050a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        return NULL;
3051a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia    }
3052a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia
3053a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
3054a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        uint32_t type;
3055a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        const void *data;
3056a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        size_t size;
3057a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        if (!track->meta->findData(kKeyAVCC, &type, &data, &size)) {
3058a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia            return NULL;
3059a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        }
3060a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia
3061a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        const uint8_t *ptr = (const uint8_t *)data;
3062a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia
3063a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        if (size < 7 || ptr[0] != 1) {  // configurationVersion == 1
3064a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia            return NULL;
3065a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        }
3066a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
3067a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        uint32_t type;
3068a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        const void *data;
3069a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        size_t size;
3070a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        if (!track->meta->findData(kKeyHVCC, &type, &data, &size)) {
3071a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia            return NULL;
3072a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        }
3073a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia
3074a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        const uint8_t *ptr = (const uint8_t *)data;
3075a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia
3076a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        if (size < 22 || ptr[0] != 1) {  // configurationVersion == 1
3077a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia            return NULL;
3078a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        }
3079a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia    }
3080a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia
3081942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    return new MPEG4Source(this,
308205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            track->meta, mDataSource, track->timescale, track->sampleTable,
3083c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            mSidxEntries, trex, mMoofOffset);
308420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
308520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3086bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber// static
3087bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) {
3088bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const char *mime;
3089bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    CHECK(track->meta->findCString(kKeyMIMEType, &mime));
3090bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
3091bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    uint32_t type;
3092bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const void *data;
3093bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    size_t size;
3094bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
3095bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyAVCC, &type, &data, &size)
3096bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeAVCC) {
3097bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
3098bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
30993b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
31003b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        if (!track->meta->findData(kKeyHVCC, &type, &data, &size)
31013b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar                    || type != kTypeHVCC) {
31023b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            return ERROR_MALFORMED;
31033b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        }
3104bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
3105ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar            || !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG2)
3106bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
3107bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyESDS, &type, &data, &size)
3108bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeESDS) {
3109bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
3110bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
3111bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    }
3112bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
3113ce171998009e1abcb0c718c0aee495fcd33645e2Robert Shih    if (track->sampleTable == NULL || !track->sampleTable->isValid()) {
3114169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        // Make sure we have all the metadata we need.
3115ce171998009e1abcb0c718c0aee495fcd33645e2Robert Shih        ALOGE("stbl atom missing/invalid.");
3116169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        return ERROR_MALFORMED;
3117169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber    }
3118169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber
31192e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang    if (track->timescale == 0) {
31202e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang        ALOGE("timescale invalid.");
31212e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang        return ERROR_MALFORMED;
31222e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang    }
31232e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang
3124bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    return OK;
3125bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber}
3126bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
3127f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivitypedef enum {
3128f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_NONE             = -1,
3129f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_NULL_OBJECT      = 0,
3130f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_MAIN         = 1, /**< Main profile                              */
3131f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_AAC_LC           = 2,   /**< Low Complexity object                     */
3132f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_SSR          = 3,
3133f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_LTP          = 4,
3134f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_SBR              = 5,
3135f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_SCAL         = 6,
3136f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_TWIN_VQ          = 7,
3137f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_CELP             = 8,
3138f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_HVXC             = 9,
3139f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_10          = 10, /**< (reserved)                                */
3140f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_11          = 11, /**< (reserved)                                */
3141f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_TTSI             = 12, /**< TTSI Object                               */
3142f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MAIN_SYNTH       = 13, /**< Main Synthetic object                     */
3143f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_WAV_TAB_SYNTH    = 14, /**< Wavetable Synthesis object                */
3144f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_GEN_MIDI         = 15, /**< General MIDI object                       */
3145f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ALG_SYNTH_AUD_FX = 16, /**< Algorithmic Synthesis and Audio FX object */
3146f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_AAC_LC        = 17,   /**< Error Resilient(ER) AAC Low Complexity    */
3147f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_18          = 18, /**< (reserved)                                */
3148f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_AAC_LTP       = 19, /**< Error Resilient(ER) AAC LTP object        */
3149f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_AAC_SCAL      = 20,   /**< Error Resilient(ER) AAC Scalable object   */
3150f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_TWIN_VQ       = 21, /**< Error Resilient(ER) TwinVQ object         */
3151f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_BSAC          = 22,   /**< Error Resilient(ER) BSAC object           */
3152f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_AAC_LD        = 23,   /**< Error Resilient(ER) AAC LowDelay object   */
3153f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_CELP          = 24, /**< Error Resilient(ER) CELP object           */
3154f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_HVXC          = 25, /**< Error Resilient(ER) HVXC object           */
3155f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_HILN          = 26, /**< Error Resilient(ER) HILN object           */
3156f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_PARA          = 27, /**< Error Resilient(ER) Parametric object     */
3157f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_28          = 28, /**< might become SSC                          */
3158f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_PS               = 29,   /**< PS, Parametric Stereo (includes SBR)      */
3159f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MPEGS            = 30, /**< MPEG Surround                             */
3160f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3161f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ESCAPE           = 31,   /**< Signal AOT uses more than 5 bits          */
3162f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3163f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MP3ONMP4_L1      = 32, /**< MPEG-Layer1 in mp4                        */
3164f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MP3ONMP4_L2      = 33, /**< MPEG-Layer2 in mp4                        */
3165f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MP3ONMP4_L3      = 34, /**< MPEG-Layer3 in mp4                        */
3166f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_35          = 35, /**< might become DST                          */
3167f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_36          = 36, /**< might become ALS                          */
3168f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_SLS          = 37, /**< AAC + SLS                                 */
3169f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_SLS              = 38, /**< SLS                                       */
3170f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_AAC_ELD       = 39, /**< AAC Enhanced Low Delay                    */
3171f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3172f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_USAC             = 42, /**< USAC                                      */
3173f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_SAOC             = 43, /**< SAOC                                      */
3174f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_LD_MPEGS         = 44, /**< Low Delay MPEG Surround                   */
3175f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3176f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD50           = 50,  /**< Interim AOT for Rsvd50                   */
3177f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi} AUDIO_OBJECT_TYPE;
3178f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3179ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
3180ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        const void *esds_data, size_t esds_size) {
3181ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    ESDS esds(esds_data, esds_size);
318281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
318381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    uint8_t objectTypeIndication;
318481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
318581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return ERROR_MALFORMED;
318681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
318781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
318881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (objectTypeIndication == 0xe1) {
318981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        // This isn't MPEG4 audio at all, it's QCELP 14k...
3190f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake        if (mLastTrack == NULL)
3191f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            return ERROR_MALFORMED;
3192f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
319381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
319481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return OK;
319581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
319681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
3197633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong    if (objectTypeIndication  == 0x6b) {
3198633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // The media subtype is MP3 audio
3199633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // Our software MP3 audio decoder may not be able to handle
3200633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // packetized MP3 audio; for now, lets just return ERROR_UNSUPPORTED
320129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("MP3 track in MP4/3GPP file is not supported");
3202633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        return ERROR_UNSUPPORTED;
3203633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong    }
3204633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong
3205ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    const uint8_t *csd;
3206ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    size_t csd_size;
3207ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (esds.getCodecSpecificInfo(
3208ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                (const void **)&csd, &csd_size) != OK) {
3209ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
3210ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
3211ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3212b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    if (kUseHexDump) {
3213ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar        printf("ESD of size %zu\n", csd_size);
3214b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        hexdump(csd, csd_size);
3215b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    }
3216ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3217a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    if (csd_size == 0) {
3218a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // There's no further information, i.e. no codec specific data
3219a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // Let's assume that the information provided in the mpeg4 headers
3220a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // is accurate and hope for the best.
3221a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
3222a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        return OK;
3223a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    }
3224a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
3225ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (csd_size < 2) {
3226ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
3227ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
3228ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
322900307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent    static uint32_t kSamplingRate[] = {
323000307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
323100307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        16000, 12000, 11025, 8000, 7350
323200307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent    };
323300307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent
3234aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    ABitReader br(csd, csd_size);
3235aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    uint32_t objectType = br.getBits(5);
3236ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3237aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    if (objectType == 31) {  // AAC-ELD => additional 6 bits
3238aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        objectType = 32 + br.getBits(6);
3239ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
3240ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3241f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake    if (mLastTrack == NULL)
3242f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake        return ERROR_MALFORMED;
3243f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
3244db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent    //keep AOT type
3245db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent    mLastTrack->meta->setInt32(kKeyAACAOT, objectType);
3246db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent
3247aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    uint32_t freqIndex = br.getBits(4);
3248aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
3249ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t sampleRate = 0;
3250ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t numChannels = 0;
3251ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (freqIndex == 15) {
32528e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen        if (br.numBitsLeft() < 28) return ERROR_MALFORMED;
3253aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        sampleRate = br.getBits(24);
3254aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        numChannels = br.getBits(4);
3255ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    } else {
32568e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen        if (br.numBitsLeft() < 4) return ERROR_MALFORMED;
3257595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen        numChannels = br.getBits(4);
325800307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent
325900307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        if (freqIndex == 13 || freqIndex == 14) {
326000307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            return ERROR_MALFORMED;
3261ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
3262ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
326300307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        sampleRate = kSamplingRate[freqIndex];
326400307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent    }
3265595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen
3266f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    if (objectType == AOT_SBR || objectType == AOT_PS) {//SBR specific config per 14496-3 table 1.13
32678e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen        if (br.numBitsLeft() < 4) return ERROR_MALFORMED;
326800307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        uint32_t extFreqIndex = br.getBits(4);
3269b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        int32_t extSampleRate __unused;
327000307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        if (extFreqIndex == 15) {
327100307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            if (csd_size < 8) {
3272595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen                return ERROR_MALFORMED;
3273595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen            }
32748e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen            if (br.numBitsLeft() < 24) return ERROR_MALFORMED;
327500307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            extSampleRate = br.getBits(24);
327600307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        } else {
327700307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            if (extFreqIndex == 13 || extFreqIndex == 14) {
327800307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent                return ERROR_MALFORMED;
327900307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            }
328000307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            extSampleRate = kSamplingRate[extFreqIndex];
3281595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen        }
328200307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        //TODO: save the extension sampling rate value in meta data =>
328300307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        //      mLastTrack->meta->setInt32(kKeyExtSampleRate, extSampleRate);
3284ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
3285ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3286f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    switch (numChannels) {
3287f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        // values defined in 14496-3_2009 amendment-4 Table 1.19 - Channel Configuration
3288f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 0:
3289f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 1:// FC
3290f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 2:// FL FR
3291f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 3:// FC, FL FR
3292f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 4:// FC, FL FR, RC
3293f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 5:// FC, FL FR, SL SR
3294f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 6:// FC, FL FR, SL SR, LFE
3295f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            //numChannels already contains the right value
3296f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            break;
3297f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 11:// FC, FL FR, SL SR, RC, LFE
3298f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            numChannels = 7;
3299f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            break;
3300f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 7: // FC, FCL FCR, FL FR, SL SR, LFE
3301f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 12:// FC, FL  FR,  SL SR, RL RR, LFE
3302f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 14:// FC, FL  FR,  SL SR, LFE, FHL FHR
3303f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            numChannels = 8;
3304f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            break;
3305f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        default:
3306f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            return ERROR_UNSUPPORTED;
3307f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    }
3308f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3309f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    {
3310f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        if (objectType == AOT_SBR || objectType == AOT_PS) {
33118e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen            if (br.numBitsLeft() < 5) return ERROR_MALFORMED;
3312f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            objectType = br.getBits(5);
3313f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3314f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            if (objectType == AOT_ESCAPE) {
33158e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                if (br.numBitsLeft() < 6) return ERROR_MALFORMED;
3316f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                objectType = 32 + br.getBits(6);
3317f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            }
3318f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        }
3319f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        if (objectType == AOT_AAC_LC || objectType == AOT_ER_AAC_LC ||
3320f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                objectType == AOT_ER_AAC_LD || objectType == AOT_ER_AAC_SCAL ||
3321f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                objectType == AOT_ER_BSAC) {
33228e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen            if (br.numBitsLeft() < 2) return ERROR_MALFORMED;
3323b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe            const int32_t frameLengthFlag __unused = br.getBits(1);
3324f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3325f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            const int32_t dependsOnCoreCoder = br.getBits(1);
3326f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3327f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            if (dependsOnCoreCoder ) {
33288e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                if (br.numBitsLeft() < 14) return ERROR_MALFORMED;
3329b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                const int32_t coreCoderDelay __unused = br.getBits(14);
3330f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            }
3331f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
333245452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            int32_t extensionFlag = -1;
333345452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            if (br.numBitsLeft() > 0) {
333445452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                extensionFlag = br.getBits(1);
333545452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            } else {
333645452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                switch (objectType) {
333745452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                // 14496-3 4.5.1.1 extensionFlag
333845452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_AAC_LC:
333945452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    extensionFlag = 0;
334045452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    break;
334145452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_ER_AAC_LC:
334245452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_ER_AAC_SCAL:
334345452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_ER_BSAC:
334445452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_ER_AAC_LD:
334545452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    extensionFlag = 1;
334645452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    break;
334745452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                default:
33488e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                    return ERROR_MALFORMED;
334945452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    break;
335045452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                }
335145452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                ALOGW("csd missing extension flag; assuming %d for object type %u.",
335245452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                        extensionFlag, objectType);
335345452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            }
3354f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
335545452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            if (numChannels == 0) {
3356f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                int32_t channelsEffectiveNum = 0;
3357f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                int32_t channelsNum = 0;
33588e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                if (br.numBitsLeft() < 32) {
33598e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                    return ERROR_MALFORMED;
33608e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                }
3361b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                const int32_t ElementInstanceTag __unused = br.getBits(4);
3362b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                const int32_t Profile __unused = br.getBits(2);
3363b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                const int32_t SamplingFrequencyIndex __unused = br.getBits(4);
3364f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumFrontChannelElements = br.getBits(4);
3365f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumSideChannelElements = br.getBits(4);
3366f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumBackChannelElements = br.getBits(4);
3367f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumLfeChannelElements = br.getBits(2);
3368b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                const int32_t NumAssocDataElements __unused = br.getBits(3);
3369b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                const int32_t NumValidCcElements __unused = br.getBits(4);
3370f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3371f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t MonoMixdownPresent = br.getBits(1);
33728e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen
3373f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                if (MonoMixdownPresent != 0) {
33748e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                    if (br.numBitsLeft() < 4) return ERROR_MALFORMED;
3375b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t MonoMixdownElementNumber __unused = br.getBits(4);
3376f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
3377f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
33788e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                if (br.numBitsLeft() < 1) return ERROR_MALFORMED;
3379f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t StereoMixdownPresent = br.getBits(1);
3380f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                if (StereoMixdownPresent != 0) {
33818e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                    if (br.numBitsLeft() < 4) return ERROR_MALFORMED;
3382b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t StereoMixdownElementNumber __unused = br.getBits(4);
3383f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
3384f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
33858e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                if (br.numBitsLeft() < 1) return ERROR_MALFORMED;
3386f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t MatrixMixdownIndexPresent = br.getBits(1);
3387f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                if (MatrixMixdownIndexPresent != 0) {
33888e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                    if (br.numBitsLeft() < 3) return ERROR_MALFORMED;
3389b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t MatrixMixdownIndex __unused = br.getBits(2);
3390b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t PseudoSurroundEnable __unused = br.getBits(1);
3391f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
3392f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3393f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                int i;
3394f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumFrontChannelElements; i++) {
33958e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                    if (br.numBitsLeft() < 5) return ERROR_MALFORMED;
3396f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t FrontElementIsCpe = br.getBits(1);
3397b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t FrontElementTagSelect __unused = br.getBits(4);
3398f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += FrontElementIsCpe ? 2 : 1;
3399f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
3400f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3401f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumSideChannelElements; i++) {
34028e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                    if (br.numBitsLeft() < 5) return ERROR_MALFORMED;
3403f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t SideElementIsCpe = br.getBits(1);
3404b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t SideElementTagSelect __unused = br.getBits(4);
3405f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += SideElementIsCpe ? 2 : 1;
3406f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
3407f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3408f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumBackChannelElements; i++) {
34098e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                    if (br.numBitsLeft() < 5) return ERROR_MALFORMED;
3410f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t BackElementIsCpe = br.getBits(1);
3411b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t BackElementTagSelect __unused = br.getBits(4);
3412f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += BackElementIsCpe ? 2 : 1;
3413f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
3414f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                channelsEffectiveNum = channelsNum;
3415f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3416f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumLfeChannelElements; i++) {
34178e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                    if (br.numBitsLeft() < 4) return ERROR_MALFORMED;
3418b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t LfeElementTagSelect __unused = br.getBits(4);
3419f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += 1;
3420f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
3421f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                ALOGV("mpeg4 audio channelsNum = %d", channelsNum);
3422f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                ALOGV("mpeg4 audio channelsEffectiveNum = %d", channelsEffectiveNum);
3423f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                numChannels = channelsNum;
3424f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            }
3425f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        }
3426f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    }
3427f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3428ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (numChannels == 0) {
3429ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_UNSUPPORTED;
3430ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
3431ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3432f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake    if (mLastTrack == NULL)
3433f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake        return ERROR_MALFORMED;
3434f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
3435ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevSampleRate;
3436ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
3437ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3438ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevSampleRate != sampleRate) {
34393856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("mpeg4 audio sample rate different from previous setting. "
3440ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevSampleRate, sampleRate);
3441ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
3442ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3443ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
3444ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3445ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevChannelCount;
3446ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
3447ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3448ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevChannelCount != numChannels) {
34493856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("mpeg4 audio channel count different from previous setting. "
3450ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevChannelCount, numChannels);
3451ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
3452ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3453ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
3454ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3455ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    return OK;
3456ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber}
3457ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
345820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
345920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
346020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::MPEG4Source(
3461942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen        const sp<MPEG4Extractor> &owner,
346220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        const sp<MetaData> &format,
3463693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &dataSource,
346448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        int32_t timeScale,
346505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const sp<SampleTable> &sampleTable,
346605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        Vector<SidxEntry> &sidx,
3467c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        const Trex *trex,
346805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t firstMoofOffset)
3469942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    : mOwner(owner),
3470942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen      mFormat(format),
347120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDataSource(dataSource),
347248c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber      mTimescale(timeScale),
347320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSampleTable(sampleTable),
347420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCurrentSampleIndex(0),
347505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentFragmentIndex(0),
347605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mSegments(sidx),
3477c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen      mTrex(trex),
347805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mFirstMoofOffset(firstMoofOffset),
347905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentMoofOffset(firstMoofOffset),
348005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentTime(0),
3481ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoAllocSize(0),
3482ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoSizes(NULL),
3483ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoOffsetsAllocSize(0),
3484ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoOffsets(NULL),
348520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mIsAVC(false),
34863b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar      mIsHEVC(false),
34876064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber      mNALLengthSize(0),
348820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mStarted(false),
348920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mGroup(NULL),
349020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mBuffer(NULL),
3491dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber      mWantsNALFragments(false),
34920024245e134467d120b40099da16c467dc365e76Andreas Huber      mSrcBuffer(NULL) {
3493ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3494c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    memset(&mTrackFragmentHeaderInfo, 0, sizeof(mTrackFragmentHeaderInfo));
3495c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
3496ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mFormat->findInt32(kKeyCryptoMode, &mCryptoMode);
349748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    mDefaultIVSize = 0;
3498ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mFormat->findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize);
3499ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t keytype;
3500ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    const void *key;
3501ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    size_t keysize;
3502ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mFormat->findData(kKeyCryptoKey, &keytype, &key, &keysize)) {
3503ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        CHECK(keysize <= 16);
3504ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memset(mCryptoKey, 0, 16);
3505ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memcpy(mCryptoKey, key, keysize);
3506ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3507ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
350820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
350920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mFormat->findCString(kKeyMIMEType, &mime);
3510dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(success);
351120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
351218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber    mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
35133b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    mIsHEVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC);
35146064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
35156064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    if (mIsAVC) {
35166064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        uint32_t type;
35176064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const void *data;
35186064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t size;
35196064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(format->findData(kKeyAVCC, &type, &data, &size));
35206064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
35216064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const uint8_t *ptr = (const uint8_t *)data;
35226064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
35236064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(size >= 7);
3524ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
35256064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
35266064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        // The number of bytes used to encode the length of a NAL unit.
35276064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        mNALLengthSize = 1 + (ptr[4] & 3);
35283b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    } else if (mIsHEVC) {
35293b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        uint32_t type;
35303b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        const void *data;
35313b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        size_t size;
35323b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        CHECK(format->findData(kKeyHVCC, &type, &data, &size));
35333b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
35343b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        const uint8_t *ptr = (const uint8_t *)data;
35353b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
3536a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        CHECK(size >= 22);
35373b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
35383b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
35393b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        mNALLengthSize = 1 + (ptr[14 + 7] & 3);
35406064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
354105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
354205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    CHECK(format->findInt32(kKeyTrackID, &mTrackId));
354305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
354405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mFirstMoofOffset != 0) {
354505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t offset = mFirstMoofOffset;
354605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        parseChunk(&offset);
354705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
354820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
354920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
355020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::~MPEG4Source() {
355120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mStarted) {
355220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        stop();
355320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
3554ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    free(mCurrentSampleInfoSizes);
3555ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    free(mCurrentSampleInfoOffsets);
355620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
355720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
355820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::start(MetaData *params) {
35597b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
35607b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
3561dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(!mStarted);
356220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
356320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t val;
3564dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (params && params->findInt32(kKeyWantsNALFragments, &val)
356520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        && val != 0) {
3566dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = true;
356720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    } else {
3568dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = false;
356920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
357020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3571afd492436efc7f66b958da14659b52232efa5910Marco Nelissen    int32_t tmp;
3572afd492436efc7f66b958da14659b52232efa5910Marco Nelissen    CHECK(mFormat->findInt32(kKeyMaxInputSize, &tmp));
3573afd492436efc7f66b958da14659b52232efa5910Marco Nelissen    size_t max_size = tmp;
357420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3575afd492436efc7f66b958da14659b52232efa5910Marco Nelissen    // A somewhat arbitrary limit that should be sufficient for 8k video frames
3576afd492436efc7f66b958da14659b52232efa5910Marco Nelissen    // If you see the message below for a valid input stream: increase the limit
3577afd492436efc7f66b958da14659b52232efa5910Marco Nelissen    if (max_size > 64 * 1024 * 1024) {
3578afd492436efc7f66b958da14659b52232efa5910Marco Nelissen        ALOGE("bogus max input size: %zu", max_size);
3579afd492436efc7f66b958da14659b52232efa5910Marco Nelissen        return ERROR_MALFORMED;
3580afd492436efc7f66b958da14659b52232efa5910Marco Nelissen    }
3581afd492436efc7f66b958da14659b52232efa5910Marco Nelissen    mGroup = new MediaBufferGroup;
3582738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    mGroup->add_buffer(new MediaBuffer(max_size));
35830024245e134467d120b40099da16c467dc365e76Andreas Huber
35848da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    mSrcBuffer = new (std::nothrow) uint8_t[max_size];
35858da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    if (mSrcBuffer == NULL) {
35868da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        // file probably specified a bad max size
3587afd492436efc7f66b958da14659b52232efa5910Marco Nelissen        delete mGroup;
3588afd492436efc7f66b958da14659b52232efa5910Marco Nelissen        mGroup = NULL;
35898da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        return ERROR_MALFORMED;
35908da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    }
359120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
359220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = true;
359320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
359420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
359520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
359620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
359720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::stop() {
35987b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
35997b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
3600dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
360120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
360220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mBuffer != NULL) {
360320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->release();
360420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
360520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
360620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36070024245e134467d120b40099da16c467dc365e76Andreas Huber    delete[] mSrcBuffer;
36080024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = NULL;
36090024245e134467d120b40099da16c467dc365e76Andreas Huber
361020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    delete mGroup;
361120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = NULL;
361220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
361320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = false;
361420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mCurrentSampleIndex = 0;
361520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
361620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
361720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
361820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
361905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseChunk(off64_t *offset) {
362005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t hdr[2];
362105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
362205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_IO;
362305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
362405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t chunk_size = ntohl(hdr[0]);
362505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t chunk_type = ntohl(hdr[1]);
362605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t data_offset = *offset + 8;
362705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
362805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (chunk_size == 1) {
362905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
363005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_IO;
363105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
363205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        chunk_size = ntoh64(chunk_size);
363305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        data_offset += 8;
363405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
363505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (chunk_size < 16) {
363605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            // The smallest valid chunk is 16 bytes long in this case.
363705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
363805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
363905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (chunk_size < 8) {
364005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // The smallest valid chunk is 8 bytes long.
364105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
364205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
364305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
364405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    char chunk[5];
364505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    MakeFourCCString(chunk_type, chunk);
3646ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar    ALOGV("MPEG4Source chunk %s @ %#llx", chunk, (long long)*offset);
364705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
364805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t chunk_data_size = *offset + chunk_size - data_offset;
364905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
365005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    switch(chunk_type) {
365105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
365205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'r', 'a', 'f'):
365305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('m', 'o', 'o', 'f'): {
365405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t stop_offset = *offset + chunk_size;
365505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset = data_offset;
365605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            while (*offset < stop_offset) {
365705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err = parseChunk(offset);
365805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (err != OK) {
365905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return err;
366005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
366105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
366205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
36633f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                // *offset points to the box following this moof. Find the next moof from there.
36643f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen
36653f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                while (true) {
36663f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
36673f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                        return ERROR_END_OF_STREAM;
36683f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    }
36693f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    chunk_size = ntohl(hdr[0]);
36703f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    chunk_type = ntohl(hdr[1]);
36713f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
36723f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                        mNextMoofOffset = *offset;
36733f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                        break;
36743f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    }
36753f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    *offset += chunk_size;
36763f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                }
367705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
367805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
367905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
368005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
368105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'f', 'h', 'd'): {
368205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err;
368305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if ((err = parseTrackFragmentHeader(data_offset, chunk_data_size)) != OK) {
368405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return err;
368505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
368605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                *offset += chunk_size;
368705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                break;
368805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
368905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
369005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'r', 'u', 'n'): {
369105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err;
369205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (mLastParsedTrackId == mTrackId) {
369305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    if ((err = parseTrackFragmentRun(data_offset, chunk_data_size)) != OK) {
369405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        return err;
369505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    }
369605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
369705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
369805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                *offset += chunk_size;
369905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                break;
370005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
370105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3702ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'a', 'i', 'z'): {
3703ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            status_t err;
3704ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((err = parseSampleAuxiliaryInformationSizes(data_offset, chunk_data_size)) != OK) {
3705ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return err;
3706ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3707ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
3708ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
3709ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3710ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'a', 'i', 'o'): {
3711ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            status_t err;
3712ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((err = parseSampleAuxiliaryInformationOffsets(data_offset, chunk_data_size)) != OK) {
3713ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return err;
3714ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3715ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
3716ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
3717ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3718ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3719ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('m', 'd', 'a', 't'): {
3720ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // parse DRM info if present
3721ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("MPEG4Source::parseChunk mdat");
3722ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // if saiz/saoi was previously observed, do something with the sampleinfos
3723ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
3724ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
3725ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3726ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
372705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        default: {
372805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset += chunk_size;
372905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
373005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
373105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
373205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
373305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
373405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
373584333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG4Source::parseSampleAuxiliaryInformationSizes(
373684333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        off64_t offset, off64_t /* size */) {
3737ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("parseSampleAuxiliaryInformationSizes");
3738ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // 14496-12 8.7.12
3739ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t version;
3740ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(
3741ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset, &version, sizeof(version))
3742ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            < (ssize_t)sizeof(version)) {
3743ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3744ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3745ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3746ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (version != 0) {
3747ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_UNSUPPORTED;
3748ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3749ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
3750ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3751ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t flags;
3752ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt24(offset, &flags)) {
3753ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3754ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3755ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 3;
3756ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3757ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (flags & 1) {
3758ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        uint32_t tmp;
3759ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
3760ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_MALFORMED;
3761ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3762ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentAuxInfoType = tmp;
3763ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        offset += 4;
3764ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
3765ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_MALFORMED;
3766ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3767ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentAuxInfoTypeParameter = tmp;
3768ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        offset += 4;
3769ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3770ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3771ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t defsize;
3772ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(offset, &defsize, 1) != 1) {
3773ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_MALFORMED;
3774ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3775ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mCurrentDefaultSampleInfoSize = defsize;
3776ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
3777ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3778ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t smplcnt;
3779ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &smplcnt)) {
3780ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_MALFORMED;
3781ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
378248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    mCurrentSampleInfoCount = smplcnt;
3783ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 4;
3784ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
378548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (mCurrentDefaultSampleInfoSize != 0) {
378648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        ALOGV("@@@@ using default sample info size of %d", mCurrentDefaultSampleInfoSize);
378748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return OK;
378848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
3789ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (smplcnt > mCurrentSampleInfoAllocSize) {
3790ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoSizes = (uint8_t*) realloc(mCurrentSampleInfoSizes, smplcnt);
3791ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoAllocSize = smplcnt;
3792ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3793ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3794ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mDataSource->readAt(offset, mCurrentSampleInfoSizes, smplcnt);
3795ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    return OK;
3796ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen}
3797ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
379884333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(
379984333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        off64_t offset, off64_t /* size */) {
3800ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("parseSampleAuxiliaryInformationOffsets");
3801ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // 14496-12 8.7.13
3802ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t version;
3803ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(offset, &version, sizeof(version)) != 1) {
3804ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3805ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3806ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
3807ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3808ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t flags;
3809ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt24(offset, &flags)) {
3810ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3811ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3812ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 3;
3813ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3814ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t entrycount;
3815ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &entrycount)) {
3816ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3817ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3818ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 4;
3819c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia    if (entrycount == 0) {
3820c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia        return OK;
3821c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia    }
3822c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia    if (entrycount > UINT32_MAX / 8) {
3823c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia        return ERROR_MALFORMED;
3824c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia    }
3825ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3826ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (entrycount > mCurrentSampleInfoOffsetsAllocSize) {
3827c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia        uint64_t *newPtr = (uint64_t *)realloc(mCurrentSampleInfoOffsets, entrycount * 8);
3828c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia        if (newPtr == NULL) {
3829c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia            return NO_MEMORY;
3830c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia        }
3831c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia        mCurrentSampleInfoOffsets = newPtr;
3832ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoOffsetsAllocSize = entrycount;
3833ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3834ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mCurrentSampleInfoOffsetCount = entrycount;
3835ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3836c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia    if (mCurrentSampleInfoOffsets == NULL) {
3837c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia        return OK;
3838c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia    }
3839c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia
3840ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < entrycount; i++) {
3841ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (version == 0) {
3842ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t tmp;
3843ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (!mDataSource->getUInt32(offset, &tmp)) {
3844ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
3845ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3846ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mCurrentSampleInfoOffsets[i] = tmp;
3847ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset += 4;
3848ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        } else {
3849ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint64_t tmp;
3850ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (!mDataSource->getUInt64(offset, &tmp)) {
3851ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
3852ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3853ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mCurrentSampleInfoOffsets[i] = tmp;
3854ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset += 8;
3855ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3856ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3857ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3858ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // parse clear/encrypted data
3859ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3860ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    off64_t drmoffset = mCurrentSampleInfoOffsets[0]; // from moof
3861ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3862ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    drmoffset += mCurrentMoofOffset;
3863ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int ivlength;
3864ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    CHECK(mFormat->findInt32(kKeyCryptoDefaultIVSize, &ivlength));
386548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
3866529c595b083f8a4c3175e2350fba5547e6008e00Marco Nelissen    // only 0, 8 and 16 byte initialization vectors are supported
3867529c595b083f8a4c3175e2350fba5547e6008e00Marco Nelissen    if (ivlength != 0 && ivlength != 8 && ivlength != 16) {
3868529c595b083f8a4c3175e2350fba5547e6008e00Marco Nelissen        ALOGW("unsupported IV length: %d", ivlength);
3869529c595b083f8a4c3175e2350fba5547e6008e00Marco Nelissen        return ERROR_MALFORMED;
3870529c595b083f8a4c3175e2350fba5547e6008e00Marco Nelissen    }
387148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    // read CencSampleAuxiliaryDataFormats
3872ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mCurrentSampleInfoCount; i++) {
3873529c595b083f8a4c3175e2350fba5547e6008e00Marco Nelissen        if (i >= mCurrentSamples.size()) {
3874529c595b083f8a4c3175e2350fba5547e6008e00Marco Nelissen            ALOGW("too few samples");
3875529c595b083f8a4c3175e2350fba5547e6008e00Marco Nelissen            break;
3876529c595b083f8a4c3175e2350fba5547e6008e00Marco Nelissen        }
3877ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Sample *smpl = &mCurrentSamples.editItemAt(i);
3878ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3879ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memset(smpl->iv, 0, 16);
3880ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (mDataSource->readAt(drmoffset, smpl->iv, ivlength) != ivlength) {
3881ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_IO;
3882ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3883ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3884ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        drmoffset += ivlength;
3885ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
388648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        int32_t smplinfosize = mCurrentDefaultSampleInfoSize;
388748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        if (smplinfosize == 0) {
388848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smplinfosize = mCurrentSampleInfoSizes[i];
3889ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
389048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        if (smplinfosize > ivlength) {
389148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint16_t numsubsamples;
389248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (!mDataSource->getUInt16(drmoffset, &numsubsamples)) {
3893ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
3894ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3895ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            drmoffset += 2;
389648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            for (size_t j = 0; j < numsubsamples; j++) {
389748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                uint16_t numclear;
389848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                uint32_t numencrypted;
389948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                if (!mDataSource->getUInt16(drmoffset, &numclear)) {
390048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                    return ERROR_IO;
390148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                }
390248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                drmoffset += 2;
390348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                if (!mDataSource->getUInt32(drmoffset, &numencrypted)) {
390448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                    return ERROR_IO;
390548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                }
390648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                drmoffset += 4;
390748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->clearsizes.add(numclear);
390848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->encryptedsizes.add(numencrypted);
3909ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
391048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        } else {
391148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smpl->clearsizes.add(0);
391248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smpl->encryptedsizes.add(smpl->size);
3913ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3914ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3915ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3916ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3917ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    return OK;
3918ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen}
3919ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
392005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentHeader(off64_t offset, off64_t size) {
392105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
392205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 8) {
392305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
392405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
392505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
392605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
3927ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags
392805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
392905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
393005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
393105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & 0xff000000) {
393205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
393305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
393405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
393505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, (uint32_t*)&mLastParsedTrackId)) {
393605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
393705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
393805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
393905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mLastParsedTrackId != mTrackId) {
394005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // this is not the right track, skip it
394105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
394205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
394305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
394405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mFlags = flags;
394505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mTrackID = mLastParsedTrackId;
394605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 8;
394705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 8;
394805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
394905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("fragment header: %08x %08x", flags, mTrackFragmentHeaderInfo.mTrackID);
395005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
395105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent) {
395205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 8) {
395305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
395405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
395505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
395605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset, &mTrackFragmentHeaderInfo.mBaseDataOffset)) {
395705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
395805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
395905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 8;
396005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 8;
396105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
396205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
396305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent) {
396405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
396505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
396605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
396705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
396805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mSampleDescriptionIndex)) {
396905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
397005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
397105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
397205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
397305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
397405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
397505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
397605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
397705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
397805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
397905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
398005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleDuration)) {
398105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
398205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
398305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
398405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
398505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
398605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
398705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
398805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
398905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
399005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
399105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
399205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleSize)) {
399305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
399405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
399505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
399605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
399705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
399805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
399905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
400005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
400105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
400205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
400305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
400405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleFlags)) {
400505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
400605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
400705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
400805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
400905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
401005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
401105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!(flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent)) {
401205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mTrackFragmentHeaderInfo.mBaseDataOffset = mCurrentMoofOffset;
401305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
401405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
401505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mDataOffset = 0;
401605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
401705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
401805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
401905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentRun(off64_t offset, off64_t size) {
402005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
402105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Extractor::parseTrackFragmentRun");
402205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 8) {
402305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
402405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
402505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
402605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    enum {
402705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kDataOffsetPresent                  = 0x01,
402805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kFirstSampleFlagsPresent            = 0x04,
402905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleDurationPresent              = 0x100,
403005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleSizePresent                  = 0x200,
403105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleFlagsPresent                 = 0x400,
403205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleCompositionTimeOffsetPresent = 0x800,
403305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
403405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
403505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
403605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) {
403705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
403805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
403905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("fragment run flags: %08x", flags);
404005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
404105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & 0xff000000) {
404205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
404305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
404405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
404505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if ((flags & kFirstSampleFlagsPresent) && (flags & kSampleFlagsPresent)) {
404605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // These two shall not be used together.
404705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
404805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
404905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
405005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t sampleCount;
405105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, &sampleCount)) {
405205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
405305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
405405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 8;
405505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 8;
405605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
405705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t dataOffset = mTrackFragmentHeaderInfo.mDataOffset;
405805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
405905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t firstSampleFlags = 0;
406005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
406105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kDataOffsetPresent) {
406205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
406305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
406405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
406505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
406605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int32_t dataOffsetDelta;
406705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, (uint32_t*)&dataOffsetDelta)) {
406805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
406905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
407005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
407105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        dataOffset = mTrackFragmentHeaderInfo.mBaseDataOffset + dataOffsetDelta;
407205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
407305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
407405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
407505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
407605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
407705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kFirstSampleFlagsPresent) {
407805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
407905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
408005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
408105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
408205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &firstSampleFlags)) {
408305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
408405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
408505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
408605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
408705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
408805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
408905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t sampleDuration = 0, sampleSize = 0, sampleFlags = 0,
409005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen             sampleCtsOffset = 0;
409105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
409205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size_t bytesPerSample = 0;
409305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleDurationPresent) {
409405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
409505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
409605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
409705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration;
4098c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    } else if (mTrex) {
4099c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        sampleDuration = mTrex->default_sample_duration;
410005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
410105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
410205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleSizePresent) {
410305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
410405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
410505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
410605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
410705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
410805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
410905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
411005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
411105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleFlagsPresent) {
411205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
411305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
411405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
411505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
411605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
411705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
411805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
411905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
412005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleCompositionTimeOffsetPresent) {
412105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
412205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
412305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleCtsOffset = 0;
412405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
412505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
4126ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar    if (size < (off64_t)(sampleCount * bytesPerSample)) {
412705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
412805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
412905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
413005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Sample tmp;
413105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    for (uint32_t i = 0; i < sampleCount; ++i) {
413205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleDurationPresent) {
413305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleDuration)) {
413405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
413505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
413605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
413705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
413805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
413905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleSizePresent) {
414005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleSize)) {
414105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
414205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
414305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
414405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
414505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
414605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleFlagsPresent) {
414705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleFlags)) {
414805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
414905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
415005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
415105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
415205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
415305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleCompositionTimeOffsetPresent) {
415405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleCtsOffset)) {
415505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
415605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
415705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
415805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
415905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
4160a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("adding sample %d at offset 0x%08" PRIx64 ", size %u, duration %u, "
4161ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen              " flags 0x%08x", i + 1,
416205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dataOffset, sampleSize, sampleDuration,
416305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                (flags & kFirstSampleFlagsPresent) && i == 0
416405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ? firstSampleFlags : sampleFlags);
416505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.offset = dataOffset;
416605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.size = sampleSize;
416705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.duration = sampleDuration;
4168c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        tmp.compositionOffset = sampleCtsOffset;
416905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentSamples.add(tmp);
417005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
417105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        dataOffset += sampleSize;
417205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
417305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
417405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mDataOffset = dataOffset;
417505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
417605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
417705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
417805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
417920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> MPEG4Source::getFormat() {
41807b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
41817b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
418220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return mFormat;
418320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
418420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
41856064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const {
41866064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    switch (mNALLengthSize) {
41876064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 1:
41886064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return *data;
41896064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 2:
41906064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U16_AT(data);
41916064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 3:
41926064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return ((size_t)data[0] << 16) | U16_AT(&data[1]);
41936064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 4:
41946064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U32_AT(data);
41956064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
41966064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
41976064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // This cannot happen, mNALLengthSize springs to life by adding 1 to
41986064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // a 2-bit integer.
41996064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    CHECK(!"Should not be here.");
42006064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
42016064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    return 0;
42026064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber}
42036064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
420420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::read(
420520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
42067b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
42077b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
4208dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
420920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
421005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mFirstMoofOffset > 0) {
421105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return fragmentedRead(out, options);
421205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
421305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
421420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *out = NULL;
421520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4216abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    int64_t targetSampleTimeUs = -1;
4217abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
421820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t seekTimeUs;
4219abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
4220abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
4221abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t findFlags = 0;
4222abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        switch (mode) {
4223abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_PREVIOUS_SYNC:
4224abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagBefore;
4225abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
4226abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_NEXT_SYNC:
4227abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagAfter;
4228abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
4229abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST_SYNC:
4230abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST:
4231abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagClosest;
4232abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
4233abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            default:
4234abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                CHECK(!"Should not be here.");
4235abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
4236abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
4237abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
423820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        uint32_t sampleIndex;
4239abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        status_t err = mSampleTable->findSampleAtTime(
4240599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar                seekTimeUs, 1000000, mTimescale,
4241abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                &sampleIndex, findFlags);
4242abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
4243abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
4244abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // We found the closest sample already, now we want the sync
4245abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // sample preceding it (or the sample itself of course), even
4246abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // if the subsequent sync sample is closer.
4247abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            findFlags = SampleTable::kFlagBefore;
4248abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
4249abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
4250abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleIndex;
4251abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (err == OK) {
4252abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            err = mSampleTable->findSyncSampleNear(
4253abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    sampleIndex, &syncSampleIndex, findFlags);
4254abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
425520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4256788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        uint32_t sampleTime;
4257788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        if (err == OK) {
4258788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber            err = mSampleTable->getMetaDataForSample(
4259788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber                    sampleIndex, NULL, NULL, &sampleTime);
4260788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        }
4261788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber
426220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (err != OK) {
42635295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            if (err == ERROR_OUT_OF_RANGE) {
42645295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // An attempt to seek past the end of the stream would
42655295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // normally cause this ERROR_OUT_OF_RANGE error. Propagating
42665295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // this all the way to the MediaPlayer would cause abnormal
42675295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // termination. Legacy behaviour appears to be to behave as if
42685295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // we had seeked to the end of stream, ending normally.
42695295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                err = ERROR_END_OF_STREAM;
42705295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            }
427105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("end of stream");
427220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return err;
427320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
427420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4275abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
4276abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
4277abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
4278abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
4279abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#if 0
4280abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleTime;
4281abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
4282abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    syncSampleIndex, NULL, NULL, &syncSampleTime));
4283abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
4284df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("seek to time %lld us => sample at time %lld us, "
4285abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             "sync sample at time %lld us",
4286abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             seekTimeUs,
4287abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             sampleTime * 1000000ll / mTimescale,
4288abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             syncSampleTime * 1000000ll / mTimescale);
4289abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#endif
4290abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
4291abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        mCurrentSampleIndex = syncSampleIndex;
429220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mBuffer != NULL) {
429320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
429420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
429520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
429620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
429720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // fall through
429820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
429920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4300c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset;
43010024245e134467d120b40099da16c467dc365e76Andreas Huber    size_t size;
4302170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih    uint32_t cts, stts;
43038bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    bool isSyncSample;
4304dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool newBuffer = false;
4305dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (mBuffer == NULL) {
4306dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        newBuffer = true;
430720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4308c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        status_t err =
4309c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber            mSampleTable->getMetaDataForSample(
4310170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                    mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample, &stts);
431120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4312dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
4313dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
4314dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
4315dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4316dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        err = mGroup->acquire_buffer(&mBuffer);
4317c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
4318dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
4319ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            CHECK(mBuffer == NULL);
4320dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
4321dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
4322c1a104aaad2d84a57bf5d87dd030d2bef56bf541Marco Nelissen        if (size > mBuffer->size()) {
4323c1a104aaad2d84a57bf5d87dd030d2bef56bf541Marco Nelissen            ALOGE("buffer too small: %zu > %zu", size, mBuffer->size());
4324c1a104aaad2d84a57bf5d87dd030d2bef56bf541Marco Nelissen            return ERROR_BUFFER_TOO_SMALL;
4325c1a104aaad2d84a57bf5d87dd030d2bef56bf541Marco Nelissen        }
43260024245e134467d120b40099da16c467dc365e76Andreas Huber    }
432720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43283b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    if ((!mIsAVC && !mIsHEVC) || mWantsNALFragments) {
4329dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (newBuffer) {
4330dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ssize_t num_bytes_read =
433134769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
4332dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4333dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            if (num_bytes_read < (ssize_t)size) {
4334dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer->release();
4335dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer = NULL;
4336dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4337dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                return ERROR_IO;
4338dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            }
4339dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
43407b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber            CHECK(mBuffer != NULL);
4341dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->set_range(0, size);
4342dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->meta_data()->clear();
434348c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mBuffer->meta_data()->setInt64(
43444678a6dc5f09008481524949a9667af5a6190374Andreas Huber                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
4345170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih            mBuffer->meta_data()->setInt64(
4346170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                    kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
4347abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
4348abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            if (targetSampleTimeUs >= 0) {
4349abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                mBuffer->meta_data()->setInt64(
4350abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                        kKeyTargetTime, targetSampleTimeUs);
4351abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            }
4352abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
43538bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            if (isSyncSample) {
43548bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
43558bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            }
43568bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
4357dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ++mCurrentSampleIndex;
4358dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
4359dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
43603b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        if (!mIsAVC && !mIsHEVC) {
4361dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            *out = mBuffer;
4362dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
4363dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4364dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return OK;
4365dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
4366dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4367dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Each NAL unit is split up into its constituent fragments and
4368dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // each one of them returned in its own buffer.
4369dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
43706064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(mBuffer->range_length() >= mNALLengthSize);
4371dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4372dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        const uint8_t *src =
4373dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
4374dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
43756064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t nal_size = parseNALSize(src);
43765d101298d8b0a78a1dc5bd26dbdada411f4ecd4dMarco Nelissen        if (mNALLengthSize > SIZE_MAX - nal_size) {
43775d101298d8b0a78a1dc5bd26dbdada411f4ecd4dMarco Nelissen            ALOGE("b/24441553, b/24445122");
43785d101298d8b0a78a1dc5bd26dbdada411f4ecd4dMarco Nelissen        }
43795d101298d8b0a78a1dc5bd26dbdada411f4ecd4dMarco Nelissen        if (mBuffer->range_length() - mNALLengthSize < nal_size) {
438029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("incomplete NAL unit.");
4381e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
4382e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer->release();
4383e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer = NULL;
4384e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
4385e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            return ERROR_MALFORMED;
4386e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        }
4387dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4388dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        MediaBuffer *clone = mBuffer->clone();
43897b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(clone != NULL);
43906064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
4391dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
43927b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(mBuffer != NULL);
4393dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mBuffer->set_range(
43946064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_offset() + mNALLengthSize + nal_size,
43956064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_length() - mNALLengthSize - nal_size);
4396dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4397dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (mBuffer->range_length() == 0) {
4398dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->release();
4399dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
4400dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
4401dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4402dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        *out = clone;
4403dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4404dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        return OK;
4405dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    } else {
4406dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Whole NAL units are returned but each fragment is prefixed by
4407dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // the start code (0x00 00 00 01).
4408dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        ssize_t num_bytes_read = 0;
4409dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        int32_t drm = 0;
4410dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
4411dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (usesDRM) {
4412dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            num_bytes_read =
4413dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
4414dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
4415dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
4416dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
441720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
441820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (num_bytes_read < (ssize_t)size) {
441920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
442020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
442120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4422dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return ERROR_IO;
442320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
442420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4425dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (usesDRM) {
4426dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK(mBuffer != NULL);
4427dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            mBuffer->set_range(0, size);
44286064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
4429dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
4430dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            uint8_t *dstData = (uint8_t *)mBuffer->data();
4431dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size_t srcOffset = 0;
4432dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size_t dstOffset = 0;
4433e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
4434dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            while (srcOffset < size) {
4435bfed843041b6aaec13ee19996748a7a1476db9c8Lajos Molnar                bool isMalFormed = !isInRange((size_t)0u, size, srcOffset, mNALLengthSize);
443634fe252c89e33572d01fea981b58d7b115e76164James Dong                size_t nalLength = 0;
443734fe252c89e33572d01fea981b58d7b115e76164James Dong                if (!isMalFormed) {
443834fe252c89e33572d01fea981b58d7b115e76164James Dong                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
443934fe252c89e33572d01fea981b58d7b115e76164James Dong                    srcOffset += mNALLengthSize;
4440bfed843041b6aaec13ee19996748a7a1476db9c8Lajos Molnar                    isMalFormed = !isInRange((size_t)0u, size, srcOffset, nalLength);
444134fe252c89e33572d01fea981b58d7b115e76164James Dong                }
4442e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
444334fe252c89e33572d01fea981b58d7b115e76164James Dong                if (isMalFormed) {
444429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                    ALOGE("Video is malformed");
4445dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    mBuffer->release();
4446dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    mBuffer = NULL;
4447dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return ERROR_MALFORMED;
4448dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
4449dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
4450dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                if (nalLength == 0) {
4451dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    continue;
4452dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
4453dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
445487afa840a40af570278e93251cfc5e55a6a3d92eMarco Nelissen                if (dstOffset > SIZE_MAX - 4 ||
445587afa840a40af570278e93251cfc5e55a6a3d92eMarco Nelissen                        dstOffset + 4 > SIZE_MAX - nalLength ||
445687afa840a40af570278e93251cfc5e55a6a3d92eMarco Nelissen                        dstOffset + 4 + nalLength > mBuffer->size()) {
445787afa840a40af570278e93251cfc5e55a6a3d92eMarco Nelissen                    ALOGE("b/27208621 : %zu %zu", dstOffset, mBuffer->size());
445887afa840a40af570278e93251cfc5e55a6a3d92eMarco Nelissen                    android_errorWriteLog(0x534e4554, "27208621");
445987afa840a40af570278e93251cfc5e55a6a3d92eMarco Nelissen                    mBuffer->release();
446087afa840a40af570278e93251cfc5e55a6a3d92eMarco Nelissen                    mBuffer = NULL;
446187afa840a40af570278e93251cfc5e55a6a3d92eMarco Nelissen                    return ERROR_MALFORMED;
446287afa840a40af570278e93251cfc5e55a6a3d92eMarco Nelissen                }
4463dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4464dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
4465dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
4466dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
4467dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 1;
4468dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
4469dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                srcOffset += nalLength;
4470dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstOffset += nalLength;
4471dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
4472dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK_EQ(srcOffset, size);
4473dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK(mBuffer != NULL);
4474dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            mBuffer->set_range(0, dstOffset);
4475dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
4476dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
447720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->meta_data()->clear();
447848c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        mBuffer->meta_data()->setInt64(
44794678a6dc5f09008481524949a9667af5a6190374Andreas Huber                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
4480170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih        mBuffer->meta_data()->setInt64(
4481170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
4482abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
4483abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (targetSampleTimeUs >= 0) {
4484abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            mBuffer->meta_data()->setInt64(
4485abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    kKeyTargetTime, targetSampleTimeUs);
4486abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
4487abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
44888bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        if (isSyncSample) {
44898bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
44908bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        }
44918bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
449220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        ++mCurrentSampleIndex;
449320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
449420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        *out = mBuffer;
449520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
449620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
449720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
449820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
449920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
450020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
450105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::fragmentedRead(
450205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MediaBuffer **out, const ReadOptions *options) {
450305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
450405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Source::fragmentedRead");
450505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
450605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    CHECK(mStarted);
450705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
450805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    *out = NULL;
450905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
451005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t targetSampleTimeUs = -1;
451105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
451205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t seekTimeUs;
451305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ReadOptions::SeekMode mode;
451405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
451505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
451605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int numSidxEntries = mSegments.size();
451705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (numSidxEntries != 0) {
451805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            int64_t totalTime = 0;
451905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t totalOffset = mFirstMoofOffset;
452005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            for (int i = 0; i < numSidxEntries; i++) {
452105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                const SidxEntry *se = &mSegments[i];
452205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (totalTime + se->mDurationUs > seekTimeUs) {
452305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    // The requested time is somewhere in this segment
45243f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    if ((mode == ReadOptions::SEEK_NEXT_SYNC && seekTimeUs > totalTime) ||
452505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        (mode == ReadOptions::SEEK_CLOSEST_SYNC &&
452605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        (seekTimeUs - totalTime) > (totalTime + se->mDurationUs - seekTimeUs))) {
452705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        // requested next sync, or closest sync and it was closer to the end of
452805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        // this segment
452905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        totalTime += se->mDurationUs;
453005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        totalOffset += se->mSize;
453105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    }
453205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    break;
453305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
453405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                totalTime += se->mDurationUs;
453505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                totalOffset += se->mSize;
453605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
4537ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentMoofOffset = totalOffset;
4538ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSamples.clear();
4539ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSampleIndex = 0;
4540ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            parseChunk(&totalOffset);
4541ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentTime = totalTime * mTimescale / 1000000ll;
4542ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen        } else {
4543ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            // without sidx boxes, we can only seek to 0
4544ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentMoofOffset = mFirstMoofOffset;
4545ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSamples.clear();
4546ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSampleIndex = 0;
4547ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            off64_t tmp = mCurrentMoofOffset;
4548ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            parseChunk(&tmp);
4549ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentTime = 0;
455005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
455105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
455205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer != NULL) {
455305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
455405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
455505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
455605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
455705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // fall through
455805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
455905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
456005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t offset = 0;
4561442cc6dc48f8188e097617f7f804c314a9dacd0eAndreas Huber    size_t size = 0;
456205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t cts = 0;
456305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    bool isSyncSample = false;
456405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    bool newBuffer = false;
456505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mBuffer == NULL) {
456605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        newBuffer = true;
456705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
456805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mCurrentSampleIndex >= mCurrentSamples.size()) {
45693f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            // move to next fragment if there is one
45703f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            if (mNextMoofOffset <= mCurrentMoofOffset) {
45713f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                return ERROR_END_OF_STREAM;
45723f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            }
4573ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            off64_t nextMoof = mNextMoofOffset;
457405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentMoofOffset = nextMoof;
457505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentSamples.clear();
457605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentSampleIndex = 0;
457705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            parseChunk(&nextMoof);
4578ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            if (mCurrentSampleIndex >= mCurrentSamples.size()) {
4579ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen                return ERROR_END_OF_STREAM;
4580ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            }
458105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
458205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
458305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
458405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset = smpl->offset;
458505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size = smpl->size;
4586c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        cts = mCurrentTime + smpl->compositionOffset;
458705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentTime += smpl->duration;
458805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        isSyncSample = (mCurrentSampleIndex == 0); // XXX
458905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
459005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        status_t err = mGroup->acquire_buffer(&mBuffer);
459105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
459205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (err != OK) {
459305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer == NULL);
459405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("acquire_buffer returned %d", err);
459505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return err;
459605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
4597c1a104aaad2d84a57bf5d87dd030d2bef56bf541Marco Nelissen        if (size > mBuffer->size()) {
4598c1a104aaad2d84a57bf5d87dd030d2bef56bf541Marco Nelissen            ALOGE("buffer too small: %zu > %zu", size, mBuffer->size());
4599c1a104aaad2d84a57bf5d87dd030d2bef56bf541Marco Nelissen            return ERROR_BUFFER_TOO_SMALL;
4600c1a104aaad2d84a57bf5d87dd030d2bef56bf541Marco Nelissen        }
460105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
460205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
460348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
460448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    const sp<MetaData> bufmeta = mBuffer->meta_data();
460548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    bufmeta->clear();
460648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (smpl->encryptedsizes.size()) {
460748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // store clear/encrypted lengths in metadata
460848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyPlainSizes, 0,
460948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->clearsizes.array(), smpl->clearsizes.size() * 4);
461048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyEncryptedSizes, 0,
461148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
461248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
461348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
461448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setInt32(kKeyCryptoMode, mCryptoMode);
461548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16);
461648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
461748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
46183b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    if ((!mIsAVC && !mIsHEVC)|| mWantsNALFragments) {
461905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (newBuffer) {
4620da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            if (!isInRange((size_t)0u, mBuffer->size(), size)) {
4621da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                mBuffer->release();
4622da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                mBuffer = NULL;
4623da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih
4624da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                ALOGE("fragmentedRead ERROR_MALFORMED size %zu", size);
4625da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                return ERROR_MALFORMED;
4626da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            }
4627da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih
462805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ssize_t num_bytes_read =
462905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
463005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
463105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (num_bytes_read < (ssize_t)size) {
463205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->release();
463305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer = NULL;
463405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
4635da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                ALOGE("i/o error");
463605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_IO;
463705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
463805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
463905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
464005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, size);
464105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt64(
464205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
4643170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih            mBuffer->meta_data()->setInt64(
4644170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                    kKeyDuration, ((int64_t)smpl->duration * 1000000) / mTimescale);
464505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
464605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (targetSampleTimeUs >= 0) {
464705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->meta_data()->setInt64(
464805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        kKeyTargetTime, targetSampleTimeUs);
464905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
465005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
465105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (isSyncSample) {
465205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
465305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
465405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
465505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ++mCurrentSampleIndex;
465605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
465705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
46583b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        if (!mIsAVC && !mIsHEVC) {
465905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *out = mBuffer;
466005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
466105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
466205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return OK;
466305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
466405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
466505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // Each NAL unit is split up into its constituent fragments and
466605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // each one of them returned in its own buffer.
466705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
466805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(mBuffer->range_length() >= mNALLengthSize);
466905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
467005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const uint8_t *src =
467105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
467205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
467305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size_t nal_size = parseNALSize(src);
46745d101298d8b0a78a1dc5bd26dbdada411f4ecd4dMarco Nelissen        if (mNALLengthSize > SIZE_MAX - nal_size) {
46755d101298d8b0a78a1dc5bd26dbdada411f4ecd4dMarco Nelissen            ALOGE("b/24441553, b/24445122");
46765d101298d8b0a78a1dc5bd26dbdada411f4ecd4dMarco Nelissen        }
46775d101298d8b0a78a1dc5bd26dbdada411f4ecd4dMarco Nelissen
46785d101298d8b0a78a1dc5bd26dbdada411f4ecd4dMarco Nelissen        if (mBuffer->range_length() - mNALLengthSize < nal_size) {
467905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGE("incomplete NAL unit.");
468005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
468105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
468205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
468305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
468405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
468505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
468605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
468705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MediaBuffer *clone = mBuffer->clone();
468805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(clone != NULL);
468905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
469005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
469105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(mBuffer != NULL);
469205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer->set_range(
469305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->range_offset() + mNALLengthSize + nal_size,
469405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->range_length() - mNALLengthSize - nal_size);
469505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
469605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer->range_length() == 0) {
469705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
469805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
469905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
470005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
470105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        *out = clone;
470205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
470305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
470405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
470505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV("whole NAL");
470605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // Whole NAL units are returned but each fragment is prefixed by
470705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // the start code (0x00 00 00 01).
470805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ssize_t num_bytes_read = 0;
470905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int32_t drm = 0;
471005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
4711da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih        void *data = NULL;
4712da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih        bool isMalFormed = false;
471305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (usesDRM) {
4714da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            if (mBuffer == NULL || !isInRange((size_t)0u, mBuffer->size(), size)) {
4715da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                isMalFormed = true;
4716da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            } else {
4717da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                data = mBuffer->data();
4718da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            }
471905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else {
4720da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            int32_t max_size;
4721da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            if (mFormat == NULL
4722da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                    || !mFormat->findInt32(kKeyMaxInputSize, &max_size)
4723da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                    || !isInRange((size_t)0u, (size_t)max_size, size)) {
4724da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                isMalFormed = true;
4725da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            } else {
4726da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                data = mSrcBuffer;
4727da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            }
472805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
472905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
4730da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih        if (isMalFormed || data == NULL) {
4731da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            ALOGE("isMalFormed size %zu", size);
4732da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            if (mBuffer != NULL) {
4733da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                mBuffer->release();
4734da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                mBuffer = NULL;
4735da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            }
4736da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            return ERROR_MALFORMED;
4737da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih        }
4738da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih        num_bytes_read = mDataSource->readAt(offset, data, size);
4739da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih
474005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (num_bytes_read < (ssize_t)size) {
474105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
474205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
474305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
4744da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            ALOGE("i/o error");
474505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_IO;
474605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
474705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
474805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (usesDRM) {
474905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
475005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, size);
475105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
475205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else {
475305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            uint8_t *dstData = (uint8_t *)mBuffer->data();
475405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            size_t srcOffset = 0;
475505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            size_t dstOffset = 0;
475605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
475705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            while (srcOffset < size) {
4758da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                isMalFormed = !isInRange((size_t)0u, size, srcOffset, mNALLengthSize);
475905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                size_t nalLength = 0;
476005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (!isMalFormed) {
476105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
476205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    srcOffset += mNALLengthSize;
4763da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                    isMalFormed = !isInRange((size_t)0u, size, srcOffset, nalLength)
4764da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                            || !isInRange((size_t)0u, mBuffer->size(), dstOffset, (size_t)4u)
4765da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                            || !isInRange((size_t)0u, mBuffer->size(), dstOffset + 4, nalLength);
476605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
476705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
476805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (isMalFormed) {
4769da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                    ALOGE("Video is malformed; nalLength %zu", nalLength);
477005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    mBuffer->release();
477105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    mBuffer = NULL;
477205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return ERROR_MALFORMED;
477305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
477405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
477505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (nalLength == 0) {
477605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    continue;
477705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
477805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
47795403587a74aee2fb57076528c3927851531c8afbMarco Nelissen                if (dstOffset > SIZE_MAX - 4 ||
47805403587a74aee2fb57076528c3927851531c8afbMarco Nelissen                        dstOffset + 4 > SIZE_MAX - nalLength ||
47815403587a74aee2fb57076528c3927851531c8afbMarco Nelissen                        dstOffset + 4 + nalLength > mBuffer->size()) {
47825403587a74aee2fb57076528c3927851531c8afbMarco Nelissen                    ALOGE("b/26365349 : %zu %zu", dstOffset, mBuffer->size());
47835403587a74aee2fb57076528c3927851531c8afbMarco Nelissen                    android_errorWriteLog(0x534e4554, "26365349");
47845403587a74aee2fb57076528c3927851531c8afbMarco Nelissen                    mBuffer->release();
47855403587a74aee2fb57076528c3927851531c8afbMarco Nelissen                    mBuffer = NULL;
47865403587a74aee2fb57076528c3927851531c8afbMarco Nelissen                    return ERROR_MALFORMED;
47875403587a74aee2fb57076528c3927851531c8afbMarco Nelissen                }
478805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
478905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
479005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
479105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
479205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 1;
479305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
479405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                srcOffset += nalLength;
479505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstOffset += nalLength;
479605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
479705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK_EQ(srcOffset, size);
479805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
479905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, dstOffset);
480005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
480105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
480205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer->meta_data()->setInt64(
480305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
4804170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih        mBuffer->meta_data()->setInt64(
4805170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                kKeyDuration, ((int64_t)smpl->duration * 1000000) / mTimescale);
480605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
480705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (targetSampleTimeUs >= 0) {
480805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt64(
480905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    kKeyTargetTime, targetSampleTimeUs);
481005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
481105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
481205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (isSyncSample) {
481305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
481405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
481505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
481605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ++mCurrentSampleIndex;
481705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
481805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        *out = mBuffer;
481905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer = NULL;
482005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
482105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
482205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
482305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
482405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
4825bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas HuberMPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix(
4826bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        const char *mimePrefix) {
4827bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    for (Track *track = mFirstTrack; track != NULL; track = track->next) {
4828bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        const char *mime;
4829bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        if (track->meta != NULL
4830bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                && track->meta->findCString(kKeyMIMEType, &mime)
4831bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) {
4832bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber            return track;
4833bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        }
4834bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    }
4835bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber
4836bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    return NULL;
4837bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber}
4838bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber
48391b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool LegacySniffMPEG4(
4840693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
484120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[8];
484220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
484334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    ssize_t n = source->readAt(4, header, sizeof(header));
484420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (n < (ssize_t)sizeof(header)) {
484520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return false;
484620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
484720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
484820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
4849b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8)
4850b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8)
48510dba73763a04d39faf999dcc5ef12af3c99535a7Andreas Huber        || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
4852ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
4853983b449a27b5fa91eca82ede5204b4341899be62Andreas Huber        || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
485418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
48555a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        *confidence = 0.4;
485620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
485720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return true;
485820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
485920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
486020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return false;
486120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
486220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
48631b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool isCompatibleBrand(uint32_t fourcc) {
48641b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    static const uint32_t kCompatibleBrands[] = {
48651b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', 'm'),
48661b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', '2'),
48671b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('a', 'v', 'c', '1'),
48683b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        FOURCC('h', 'v', 'c', '1'),
48693b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        FOURCC('h', 'e', 'v', '1'),
48701b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('3', 'g', 'p', '4'),
48711b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '1'),
48721b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '2'),
48734cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong
48744cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        // Won't promise that the following file types can be played.
48754cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        // Just give these file types a chance.
48764cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        FOURCC('q', 't', ' ', ' '),  // Apple's QuickTime
48774cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        FOURCC('M', 'S', 'N', 'V'),  // Sony's PSP
487858fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber
487958fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber        FOURCC('3', 'g', '2', 'a'),  // 3GPP2
488058fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber        FOURCC('3', 'g', '2', 'b'),
48811b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    };
48821b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
48831b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    for (size_t i = 0;
48841b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]);
48851b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         ++i) {
48861b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        if (kCompatibleBrands[i] == fourcc) {
48871b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            return true;
48881b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
48891b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
48901b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
48911b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
48921b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
48931b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
48941b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// Attempt to actually parse the 'ftyp' atom and determine if a suitable
48951b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// compatible brand is present.
4896a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// Also try to identify where this file's metadata ends
4897a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// (end of the 'moov' atom) and report it to the caller as part of
4898a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// the metadata.
48991b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool BetterSniffMPEG4(
4900a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
4901a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        sp<AMessage> *meta) {
4902a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    // We scan up to 128 bytes to identify this file as an MP4.
4903a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    static const off64_t kMaxScanOffset = 128ll;
49041b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4905a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    off64_t offset = 0ll;
4906a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    bool foundGoodFileType = false;
4907a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    off64_t moovAtomEndOffset = -1ll;
4908a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    bool done = false;
49091b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4910a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    while (!done && offset < kMaxScanOffset) {
4911a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint32_t hdr[2];
4912a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        if (source->readAt(offset, hdr, 8) < 8) {
4913a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            return false;
4914a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        }
4915a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4916a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint64_t chunkSize = ntohl(hdr[0]);
4917a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint32_t chunkType = ntohl(hdr[1]);
4918a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        off64_t chunkDataOffset = offset + 8;
4919a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4920a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        if (chunkSize == 1) {
4921a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            if (source->readAt(offset + 8, &chunkSize, 8) < 8) {
49221b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                return false;
49231b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
49241b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4925a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            chunkSize = ntoh64(chunkSize);
4926a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            chunkDataOffset += 8;
4927a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4928a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            if (chunkSize < 16) {
4929a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                // The smallest valid chunk is 16 bytes long in this case.
4930a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                return false;
4931a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            }
4932452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen
4933a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        } else if (chunkSize < 8) {
4934a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            // The smallest valid chunk is 8 bytes long.
4935a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            return false;
4936a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        }
4937a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4938452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen        // (data_offset - offset) is either 8 or 16
4939452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen        off64_t chunkDataSize = chunkSize - (chunkDataOffset - offset);
4940452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen        if (chunkDataSize < 0) {
4941452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen            ALOGE("b/23540914");
4942452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen            return ERROR_MALFORMED;
4943452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen        }
4944a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
494505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        char chunkstring[5];
494605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MakeFourCCString(chunkType, chunkstring);
4947ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar        ALOGV("saw chunk type %s, size %" PRIu64 " @ %lld", chunkstring, chunkSize, (long long)offset);
4948a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        switch (chunkType) {
4949a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            case FOURCC('f', 't', 'y', 'p'):
4950a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            {
4951a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                if (chunkDataSize < 8) {
4952a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    return false;
4953a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
4954a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4955a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4;
4956a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
4957a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (i == 1) {
4958a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        // Skip this index, it refers to the minorVersion,
4959a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        // not a brand.
4960a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        continue;
4961a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
4962a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4963a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    uint32_t brand;
4964a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (source->readAt(
4965a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                                chunkDataOffset + 4 * i, &brand, 4) < 4) {
4966a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        return false;
4967a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
4968a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4969a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    brand = ntohl(brand);
4970a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4971a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (isCompatibleBrand(brand)) {
4972a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        foundGoodFileType = true;
4973a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        break;
4974a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
4975a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
4976a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4977a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                if (!foundGoodFileType) {
4978a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    return false;
4979a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
4980a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
49811b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                break;
49821b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
4983a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4984a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            case FOURCC('m', 'o', 'o', 'v'):
4985a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            {
4986a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                moovAtomEndOffset = offset + chunkSize;
4987a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4988a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                done = true;
4989a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                break;
4990a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            }
4991a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4992a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            default:
4993a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                break;
49941b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
4995a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4996a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        offset += chunkSize;
49971b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
49981b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4999a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (!foundGoodFileType) {
50001b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return false;
50011b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
50021b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
50031b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
50045a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber    *confidence = 0.4f;
50051b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
5006a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (moovAtomEndOffset >= 0) {
5007a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        *meta = new AMessage;
5008a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        (*meta)->setInt64("meta-data-size", moovAtomEndOffset);
5009a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
5010ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar        ALOGV("found metadata size: %lld", (long long)moovAtomEndOffset);
5011a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    }
5012a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
50131b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return true;
50141b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
50151b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
50161b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberbool SniffMPEG4(
50175a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
5018a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        sp<AMessage> *meta) {
5019a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (BetterSniffMPEG4(source, mimeType, confidence, meta)) {
50201b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
50211b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
50221b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
50231b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    if (LegacySniffMPEG4(source, mimeType, confidence)) {
50245ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Identified supported mpeg4 through LegacySniffMPEG4.");
50251b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
50261b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
50271b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
50281b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
50291b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
50301b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
503120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
5032