MPEG4Extractor.cpp revision 2fae4e4cb6b3039f28810e827de75b0612fadd83
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
540dc8be97f0fbee707b69b24b3a8d914f88c77423Lajos Molnarenum {
550dc8be97f0fbee707b69b24b3a8d914f88c77423Lajos Molnar    // max track header chunk to return
560dc8be97f0fbee707b69b24b3a8d914f88c77423Lajos Molnar    kMaxTrackHeaderSize = 32,
572fae4e4cb6b3039f28810e827de75b0612fadd83Marco Nelissen
582fae4e4cb6b3039f28810e827de75b0612fadd83Marco Nelissen    // maximum size of an atom. Some atoms can be bigger according to the spec,
592fae4e4cb6b3039f28810e827de75b0612fadd83Marco Nelissen    // but we only allow up to this size.
602fae4e4cb6b3039f28810e827de75b0612fadd83Marco Nelissen    kMaxAtomSize = 64 * 1024 * 1024,
610dc8be97f0fbee707b69b24b3a8d914f88c77423Lajos Molnar};
620dc8be97f0fbee707b69b24b3a8d914f88c77423Lajos Molnar
6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Source : public MediaSource {
6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Caller retains ownership of both "dataSource" and "sampleTable".
66942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    MPEG4Source(const sp<MPEG4Extractor> &owner,
67942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen                const sp<MetaData> &format,
68693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber                const sp<DataSource> &dataSource,
6948c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                int32_t timeScale,
7005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                const sp<SampleTable> &sampleTable,
7105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                Vector<SidxEntry> &sidx,
72c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                const Trex *trex,
7305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                off64_t firstMoofOffset);
7420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t start(MetaData *params = NULL);
7620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t stop();
7720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual sp<MetaData> getFormat();
7920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL);
8105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    virtual status_t fragmentedRead(MediaBuffer **buffer, const ReadOptions *options = NULL);
8220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
83693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huberprotected:
84693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    virtual ~MPEG4Source();
85693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber
8620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
877b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex mLock;
887b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
89942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    // keep the MPEG4Extractor around, since we're referencing its data
90942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    sp<MPEG4Extractor> mOwner;
9120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mFormat;
92693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<DataSource> mDataSource;
9320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t mTimescale;
94693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<SampleTable> mSampleTable;
9520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t mCurrentSampleIndex;
9605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t mCurrentFragmentIndex;
9705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Vector<SidxEntry> &mSegments;
98c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    const Trex *mTrex;
9905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mFirstMoofOffset;
10005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mCurrentMoofOffset;
10105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mNextMoofOffset;
10205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t mCurrentTime;
10305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int32_t mLastParsedTrackId;
10405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int32_t mTrackId;
10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
106ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int32_t mCryptoMode;    // passed in from extractor
107ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int32_t mDefaultIVSize; // passed in from extractor
108ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t mCryptoKey[16]; // passed in from extractor
109ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentAuxInfoType;
110ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentAuxInfoTypeParameter;
11148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    int32_t mCurrentDefaultSampleInfoSize;
112ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoCount;
113ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoAllocSize;
114ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t* mCurrentSampleInfoSizes;
115ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoOffsetCount;
116ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoOffsetsAllocSize;
117ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint64_t* mCurrentSampleInfoOffsets;
118ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
11920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mIsAVC;
1203b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    bool mIsHEVC;
1216064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    size_t mNALLengthSize;
1226064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
12320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mStarted;
12420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBufferGroup *mGroup;
12620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *mBuffer;
12820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
129dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool mWantsNALFragments;
13020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1310024245e134467d120b40099da16c467dc365e76Andreas Huber    uint8_t *mSrcBuffer;
1320024245e134467d120b40099da16c467dc365e76Andreas Huber
1336064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    size_t parseNALSize(const uint8_t *data) const;
13405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseChunk(off64_t *offset);
13505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseTrackFragmentHeader(off64_t offset, off64_t size);
13605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseTrackFragmentRun(off64_t offset, off64_t size);
137ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    status_t parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size);
138ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    status_t parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size);
13905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
14005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    struct TrackFragmentHeaderInfo {
14105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        enum Flags {
14205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kBaseDataOffsetPresent         = 0x01,
14305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kSampleDescriptionIndexPresent = 0x02,
14405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleDurationPresent  = 0x08,
14505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleSizePresent      = 0x10,
14605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleFlagsPresent     = 0x20,
14705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDurationIsEmpty               = 0x10000,
14805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        };
14905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
15005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mTrackID;
15105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mFlags;
15205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint64_t mBaseDataOffset;
15305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mSampleDescriptionIndex;
15405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleDuration;
15505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleSize;
15605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleFlags;
15705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
15805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint64_t mDataOffset;
15905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
16005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    TrackFragmentHeaderInfo mTrackFragmentHeaderInfo;
16105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
16205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    struct Sample {
16305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t offset;
16405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size_t size;
16505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t duration;
166c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        int32_t compositionOffset;
167ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        uint8_t iv[16];
168ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Vector<size_t> clearsizes;
169ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Vector<size_t> encryptedsizes;
17005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
17105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Vector<Sample> mCurrentSamples;
1726064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
17320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source(const MPEG4Source &);
17420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source &operator=(const MPEG4Source &);
17520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
17620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This custom data source wraps an existing one and satisfies requests
17850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// falling entirely within a cached range from the cache while forwarding
17950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// all remaining requests to the wrapped datasource.
18050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This is used to cache the full sampletable metadata for a single track,
18150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// possibly wrapping multiple times to cover all tracks, i.e.
18250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// Each MPEG4DataSource caches the sampletable metadata for a single track.
18350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstruct MPEG4DataSource : public DataSource {
18550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource(const sp<DataSource> &source);
18650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual status_t initCheck() const;
188c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
189c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    virtual status_t getSize(off64_t *size);
19050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual uint32_t flags();
19150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
192c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    status_t setCachedRange(off64_t offset, size_t size);
19350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprotected:
19550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual ~MPEG4DataSource();
19650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprivate:
19850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex mLock;
19950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
20050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    sp<DataSource> mSource;
201c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t mCachedOffset;
20250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    size_t mCachedSize;
20350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    uint8_t *mCache;
20450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
20550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    void clearCache();
20650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
20750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource(const MPEG4DataSource &);
20850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource &operator=(const MPEG4DataSource &);
20950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber};
21050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
21150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source)
21250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    : mSource(source),
21350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCachedOffset(0),
21450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCachedSize(0),
21550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCache(NULL) {
21650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
21750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
21850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::~MPEG4DataSource() {
21950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    clearCache();
22050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
22150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
22250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Hubervoid MPEG4DataSource::clearCache() {
22350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (mCache) {
22450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        free(mCache);
22550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        mCache = NULL;
22650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
22750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
22850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedOffset = 0;
22950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedSize = 0;
23050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
23150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
23250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstatus_t MPEG4DataSource::initCheck() const {
23350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->initCheck();
23450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
23550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
236c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongssize_t MPEG4DataSource::readAt(off64_t offset, void *data, size_t size) {
23750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex::Autolock autoLock(mLock);
23850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
239bfed843041b6aaec13ee19996748a7a1476db9c8Lajos Molnar    if (isInRange(mCachedOffset, mCachedSize, offset, size)) {
24050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        memcpy(data, &mCache[offset - mCachedOffset], size);
24150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return size;
24250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
24350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
24450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->readAt(offset, data, size);
24550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
24650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
247c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4DataSource::getSize(off64_t *size) {
24850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->getSize(size);
24950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
25050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
25150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberuint32_t MPEG4DataSource::flags() {
25250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->flags();
25350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
25450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
255c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4DataSource::setCachedRange(off64_t offset, size_t size) {
25650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex::Autolock autoLock(mLock);
25750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
25850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    clearCache();
25950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
26050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCache = (uint8_t *)malloc(size);
26150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
26250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (mCache == NULL) {
26350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return -ENOMEM;
26450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
26550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
26650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedOffset = offset;
26750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedSize = size;
26850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
26950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    ssize_t err = mSource->readAt(mCachedOffset, mCache, mCachedSize);
27050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
27150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (err < (ssize_t)size) {
27250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        clearCache();
27350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
27450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return ERROR_IO;
27550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
27650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
27750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return OK;
27850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
27950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
28050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber////////////////////////////////////////////////////////////////////////////////
28150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
282b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampestatic const bool kUseHexDump = false;
283b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe
28420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatic void hexdump(const void *_data, size_t size) {
28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const uint8_t *data = (const uint8_t *)_data;
28620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t offset = 0;
28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (offset < size) {
288377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        printf("0x%04zx  ", offset);
28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        size_t n = size - offset;
29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (n > 16) {
29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            n = 16;
29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < 16; ++i) {
29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (i == 8) {
29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(" ");
29820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
29920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (offset + i < size) {
30120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%02x ", data[offset + i]);
30220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
30320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("   ");
30420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
30520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
30620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf(" ");
30820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < n; ++i) {
31020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (isprint(data[offset + i])) {
31120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%c", data[offset + i]);
31220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
31320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(".");
31420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
31520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
31620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf("\n");
31820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        offset += 16;
32020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
32120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
32220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huberstatic const char *FourCC2MIME(uint32_t fourcc) {
32420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch (fourcc) {
32520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
32618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AAC;
32720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
32918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_NB;
33020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
331371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
33218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_WB;
333371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
33420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
33518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_MPEG4;
33620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
338e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('h', '2', '6', '3'):
339e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('H', '2', '6', '3'):
34018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_H263;
34120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
34220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
34318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_AVC;
34420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3453b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'v', 'c', '1'):
3463b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'e', 'v', '1'):
3473b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            return MEDIA_MIMETYPE_VIDEO_HEVC;
34820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
349dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(!"should not be here.");
35020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
35120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
35220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
35320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissenstatic bool AdjustChannelsAndRate(uint32_t fourcc, uint32_t *channels, uint32_t *rate) {
35548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, FourCC2MIME(fourcc))) {
35648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // AMR NB audio is always mono, 8kHz
35748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *channels = 1;
35848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *rate = 8000;
35948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return true;
36048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, FourCC2MIME(fourcc))) {
36148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // AMR WB audio is always mono, 16kHz
36248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *channels = 1;
36348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *rate = 16000;
36448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return true;
36548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
36648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    return false;
36748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen}
36848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
369693d271e62a3726689ff68f4505ba49228eb94b2Andreas HuberMPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
370c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    : mMoofOffset(0),
371928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang      mMoofFound(false),
372928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang      mMdatFound(false),
37305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mDataSource(source),
374bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber      mInitCheck(NO_INIT),
3757be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber      mHasVideo(false),
376fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen      mHeaderTimescale(0),
37720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mFirstTrack(NULL),
37872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber      mLastTrack(NULL),
379dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mFileMetaData(new MetaData),
380dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mFirstSINF(NULL),
381dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mIsDrm(false) {
38220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
38320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
38420111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Extractor::~MPEG4Extractor() {
38520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
38620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
38720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        Track *next = track->next;
38820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
38920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete track;
39020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = next;
39120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
39220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFirstTrack = mLastTrack = NULL;
393dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
394dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    SINF *sinf = mFirstSINF;
395dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (sinf) {
396dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        SINF *next = sinf->next;
3978da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        delete[] sinf->IPMPData;
398dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        delete sinf;
399dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf = next;
400dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
401dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    mFirstSINF = NULL;
402ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
403ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mPssh.size(); i++) {
404ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        delete [] mPssh[i].data;
405ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
40620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
40720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
40805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenuint32_t MPEG4Extractor::flags() const {
40905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return CAN_PAUSE |
41005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ((mMoofOffset == 0 || mSidxEntries.size() != 0) ?
41105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    (CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK) : 0);
41205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
41305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
4147be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Hubersp<MetaData> MPEG4Extractor::getMetaData() {
4157be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    status_t err;
4167be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    if ((err = readMetaData()) != OK) {
41772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return new MetaData;
4187be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    }
4197be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
42072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return mFileMetaData;
4217be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber}
4227be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
423693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersize_t MPEG4Extractor::countTracks() {
42420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
42520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
426ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        ALOGV("MPEG4Extractor::countTracks: no tracks");
427693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return 0;
42820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
42920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
430693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    size_t n = 0;
43120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
43220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
433693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        ++n;
43420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
43520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
437a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("MPEG4Extractor::countTracks: %zu tracks", n);
438693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    return n;
43920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
44020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4417e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Hubersp<MetaData> MPEG4Extractor::getTrackMetaData(
4427e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        size_t index, uint32_t flags) {
44320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
44420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
44520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return NULL;
44620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
44720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
44820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
44920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
45020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
45120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
45220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
45320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
45420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
45520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
45620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
45720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
458371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
459371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
460371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
461371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
4627e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    if ((flags & kIncludeExtensiveMetaData)
4637e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            && !track->includes_expensive_metadata) {
4647e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        track->includes_expensive_metadata = true;
4657e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
4667e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        const char *mime;
4677e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        CHECK(track->meta->findCString(kKeyMIMEType, &mime));
4687e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        if (!strncasecmp("video/", mime, 6)) {
46905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (mMoofOffset > 0) {
47005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                int64_t duration;
47105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (track->meta->findInt64(kKeyDuration, &duration)) {
47205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    // nothing fancy, just pick a frame near 1/4th of the duration
47305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    track->meta->setInt64(
47405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            kKeyThumbnailTime, duration / 4);
47505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
47605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            } else {
47705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t sampleIndex;
47805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t sampleTime;
47905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK
48005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        && track->sampleTable->getMetaDataForSample(
48105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            sampleIndex, NULL /* offset */, NULL /* size */,
48205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            &sampleTime) == OK) {
48305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    track->meta->setInt64(
48405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            kKeyThumbnailTime,
48505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            ((int64_t)sampleTime * 1000000) / track->timescale);
48605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
4877e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            }
4880dc8be97f0fbee707b69b24b3a8d914f88c77423Lajos Molnar
4890dc8be97f0fbee707b69b24b3a8d914f88c77423Lajos Molnar            // MPEG2 tracks do not provide CSD, so read the stream header
4900dc8be97f0fbee707b69b24b3a8d914f88c77423Lajos Molnar            if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG2)) {
4910dc8be97f0fbee707b69b24b3a8d914f88c77423Lajos Molnar                off64_t offset;
4920dc8be97f0fbee707b69b24b3a8d914f88c77423Lajos Molnar                size_t size;
4930dc8be97f0fbee707b69b24b3a8d914f88c77423Lajos Molnar                if (track->sampleTable->getMetaDataForSample(
4940dc8be97f0fbee707b69b24b3a8d914f88c77423Lajos Molnar                            0 /* sampleIndex */, &offset, &size, NULL /* sampleTime */) == OK) {
4950dc8be97f0fbee707b69b24b3a8d914f88c77423Lajos Molnar                    if (size > kMaxTrackHeaderSize) {
4960dc8be97f0fbee707b69b24b3a8d914f88c77423Lajos Molnar                        size = kMaxTrackHeaderSize;
4970dc8be97f0fbee707b69b24b3a8d914f88c77423Lajos Molnar                    }
4980dc8be97f0fbee707b69b24b3a8d914f88c77423Lajos Molnar                    uint8_t header[kMaxTrackHeaderSize];
4990dc8be97f0fbee707b69b24b3a8d914f88c77423Lajos Molnar                    if (mDataSource->readAt(offset, &header, size) == (ssize_t)size) {
5000dc8be97f0fbee707b69b24b3a8d914f88c77423Lajos Molnar                        track->meta->setData(kKeyStreamHeader, 'mdat', header, size);
5010dc8be97f0fbee707b69b24b3a8d914f88c77423Lajos Molnar                    }
5020dc8be97f0fbee707b69b24b3a8d914f88c77423Lajos Molnar                }
5030dc8be97f0fbee707b69b24b3a8d914f88c77423Lajos Molnar            }
5047e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        }
5057e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    }
5067e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
50720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return track->meta;
50820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
50920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
51048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissenstatic void MakeFourCCString(uint32_t x, char *s) {
51148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[0] = x >> 24;
51248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[1] = (x >> 16) & 0xff;
51348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[2] = (x >> 8) & 0xff;
51448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[3] = x & 0xff;
51548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[4] = '\0';
51648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen}
51748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
51820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Extractor::readMetaData() {
519bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    if (mInitCheck != NO_INIT) {
520bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        return mInitCheck;
52120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
52220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
523c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = 0;
52420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
525928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang    bool sawMoovOrSidx = false;
526928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang
527928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang    while (!(sawMoovOrSidx && (mMdatFound || mMoofFound))) {
528a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen        off64_t orig_offset = offset;
52905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        err = parseChunk(&offset, 0);
530a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen
5314ff2a0dbb178c4ea652f30aa4f1d3deb9fdbc832Lajos Molnar        if (err != OK && err != UNKNOWN_ERROR) {
5324ff2a0dbb178c4ea652f30aa4f1d3deb9fdbc832Lajos Molnar            break;
5334ff2a0dbb178c4ea652f30aa4f1d3deb9fdbc832Lajos Molnar        } else if (offset <= orig_offset) {
534a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            // only continue parsing if the offset was advanced,
535a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            // otherwise we might end up in an infinite loop
536ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar            ALOGE("did not advance: %lld->%lld", (long long)orig_offset, (long long)offset);
537a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            err = ERROR_MALFORMED;
538a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            break;
539928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang        } else if (err == UNKNOWN_ERROR) {
540928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang            sawMoovOrSidx = true;
54105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
54220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
5437be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
544bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    if (mInitCheck == OK) {
54572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        if (mHasVideo) {
546bc8b5faec8a0a9ad7c8d94945e7b000d63f0afe6Andreas Huber            mFileMetaData->setCString(
547bc8b5faec8a0a9ad7c8d94945e7b000d63f0afe6Andreas Huber                    kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG4);
54872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else {
54972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
55072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
551bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    } else {
552bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        mInitCheck = err;
55320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
55420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
555bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    CHECK_NE(err, (status_t)NO_INIT);
556ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
557ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // copy pssh data into file metadata
558c9b255b7f771f55462cadd34e109bfee3bf80a3aMarco Nelissen    uint64_t psshsize = 0;
559ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mPssh.size(); i++) {
560ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        psshsize += 20 + mPssh[i].datalen;
561ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
562c9b255b7f771f55462cadd34e109bfee3bf80a3aMarco Nelissen    if (psshsize > 0 && psshsize <= UINT32_MAX) {
563ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        char *buf = (char*)malloc(psshsize);
5646a456937c0d42fd8617126afdbf9e41087cf3cbcMarco Nelissen        if (!buf) {
5656a456937c0d42fd8617126afdbf9e41087cf3cbcMarco Nelissen            ALOGE("b/28471206");
5666a456937c0d42fd8617126afdbf9e41087cf3cbcMarco Nelissen            return NO_MEMORY;
5676a456937c0d42fd8617126afdbf9e41087cf3cbcMarco Nelissen        }
568ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        char *ptr = buf;
569ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        for (size_t i = 0; i < mPssh.size(); i++) {
570ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memcpy(ptr, mPssh[i].uuid, 20); // uuid + length
571ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memcpy(ptr + 20, mPssh[i].data, mPssh[i].datalen);
572ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ptr += (20 + mPssh[i].datalen);
573ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
574ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mFileMetaData->setData(kKeyPssh, 'pssh', buf, psshsize);
575ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        free(buf);
576ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
577bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    return mInitCheck;
57820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
57920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
580dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wangchar* MPEG4Extractor::getDrmTrackInfo(size_t trackID, int *len) {
581dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mFirstSINF == NULL) {
582dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return NULL;
583dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
584dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
585dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    SINF *sinf = mFirstSINF;
586dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (sinf && (trackID != sinf->trackID)) {
587dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf = sinf->next;
588dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
589dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
590dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (sinf == NULL) {
591dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return NULL;
592dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
593dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
594dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    *len = sinf->len;
595dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return sinf->IPMPData;
596dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
597dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
598dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang// Reads an encoded integer 7 bits at a time until it encounters the high bit clear.
59956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenstatic int32_t readSize(off64_t offset,
600dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        const sp<DataSource> DataSource, uint8_t *numOfBytes) {
601dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint32_t size = 0;
602dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t data;
603dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    bool moreData = true;
604dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    *numOfBytes = 0;
605dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
606dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (moreData) {
607dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (DataSource->readAt(offset, &data, 1) < 1) {
608dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return -1;
609dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
610dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        offset ++;
611dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        moreData = (data >= 128) ? true : false;
612dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        size = (size << 7) | (data & 0x7f); // Take last 7 bits
613dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        (*numOfBytes) ++;
614dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
615dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
616dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return size;
617dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
618dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
61984333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG4Extractor::parseDrmSINF(
62084333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        off64_t * /* offset */, off64_t data_offset) {
621dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t updateIdTag;
622dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
623dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
624dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
625dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset ++;
626dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
627dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (0x01/*OBJECT_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
628dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
629dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
630dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
631dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t numOfBytes;
632dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    int32_t size = readSize(data_offset, mDataSource, &numOfBytes);
633dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size < 0) {
634dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
635dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
636dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset += numOfBytes;
637dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
638dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while(size >= 11 ) {
639dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t descriptorTag;
640dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, &descriptorTag, 1) < 1) {
641dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
642dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
643dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset ++;
644dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
645dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (0x11/*OBJECT_DESCRIPTOR_ID_TAG*/ != descriptorTag) {
646dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
647dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
648dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
649dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t buffer[8];
650dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        //ObjectDescriptorID and ObjectDescriptor url flag
651dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, buffer, 2) < 2) {
652dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
653dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
654dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset += 2;
655dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
656dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if ((buffer[1] >> 5) & 0x0001) { //url flag is set
657dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
658dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
659dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
660dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, buffer, 8) < 8) {
661dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
662dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
663dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset += 8;
664dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
665dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if ((0x0F/*ES_ID_REF_TAG*/ != buffer[1])
666dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                || ( 0x0A/*IPMP_DESCRIPTOR_POINTER_ID_TAG*/ != buffer[5])) {
667dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
668dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
669dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
670dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        SINF *sinf = new SINF;
671dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->trackID = U16_AT(&buffer[3]);
672dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->IPMPDescriptorID = buffer[7];
673dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->next = mFirstSINF;
674dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        mFirstSINF = sinf;
675dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
676dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        size -= (8 + 2 + 1);
677dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
678dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
679dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size != 0) {
680dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
681dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
682dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
683dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
684dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
685dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
686dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset ++;
687dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
688dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if(0x05/*IPMP_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
689dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
690dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
691dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
692dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    size = readSize(data_offset, mDataSource, &numOfBytes);
693dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size < 0) {
694dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
695dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
696dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset += numOfBytes;
697dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
698dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (size > 0) {
699dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t tag;
700dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        int32_t dataLen;
701dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, &tag, 1) < 1) {
702dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
703dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
704dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset ++;
705dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
706dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (0x0B/*IPMP_DESCRIPTOR_ID_TAG*/ == tag) {
707dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            uint8_t id;
708dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            dataLen = readSize(data_offset, mDataSource, &numOfBytes);
709dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (dataLen < 0) {
710dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
711dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            } else if (dataLen < 4) {
712dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
713dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
714dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset += numOfBytes;
715dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
716dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (mDataSource->readAt(data_offset, &id, 1) < 1) {
717dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
718dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
719dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset ++;
720dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
721dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            SINF *sinf = mFirstSINF;
722dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            while (sinf && (sinf->IPMPDescriptorID != id)) {
723dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                sinf = sinf->next;
724dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
725dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (sinf == NULL) {
726dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
727dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
728dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            sinf->len = dataLen - 3;
7298da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            sinf->IPMPData = new (std::nothrow) char[sinf->len];
7308da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            if (sinf->IPMPData == NULL) {
7318da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen                return ERROR_MALFORMED;
7328da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            }
733f7df9ab3187a3c02bffe1fba10d3fb95197e4a07Ichitaro Kohara            data_offset += 2;
734dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
735f7df9ab3187a3c02bffe1fba10d3fb95197e4a07Ichitaro Kohara            if (mDataSource->readAt(data_offset, sinf->IPMPData, sinf->len) < sinf->len) {
736dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
737dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
738dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset += sinf->len;
739dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
740dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size -= (dataLen + numOfBytes + 1);
741dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
742dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
743dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
744dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size != 0) {
745dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
746dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
747dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
748dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return UNKNOWN_ERROR;  // Return a dummy error.
749dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
750dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
75172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstruct PathAdder {
75272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder(Vector<uint32_t> *path, uint32_t chunkType)
75372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        : mPath(path) {
75472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        mPath->push(chunkType);
75572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
75672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
75772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    ~PathAdder() {
75872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        mPath->pop();
75972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
76072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
76172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberprivate:
76272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    Vector<uint32_t> *mPath;
76372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
76472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder(const PathAdder &);
76572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder &operator=(const PathAdder &);
76672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber};
76772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
76872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic bool underMetaDataPath(const Vector<uint32_t> &path) {
76972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return path.size() >= 5
77072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[0] == FOURCC('m', 'o', 'o', 'v')
77172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[1] == FOURCC('u', 'd', 't', 'a')
77272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[2] == FOURCC('m', 'e', 't', 'a')
77372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[3] == FOURCC('i', 'l', 's', 't');
77472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
77572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
7768cfad968d5ec429b033caff9743f1ef15090be61Chong Zhangstatic bool underQTMetaPath(const Vector<uint32_t> &path, int32_t depth) {
7778cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    return path.size() >= 2
7788cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            && path[0] == FOURCC('m', 'o', 'o', 'v')
7798cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            && path[1] == FOURCC('m', 'e', 't', 'a')
7808cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            && (depth == 2
7818cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            || (depth == 3
782ef185e94ce624146e3b1f3cbdb2404e833a0f81dChong Zhang                    && (path[2] == FOURCC('h', 'd', 'l', 'r')
783ef185e94ce624146e3b1f3cbdb2404e833a0f81dChong Zhang                    ||  path[2] == FOURCC('i', 'l', 's', 't')
7848cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    ||  path[2] == FOURCC('k', 'e', 'y', 's'))));
7858cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang}
7868cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
78772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber// Given a time in seconds since Jan 1 1904, produce a human-readable string.
7883724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissenstatic bool convertTimeToDate(int64_t time_1904, String8 *s) {
7893724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen    // delta between mpeg4 time and unix epoch time
7903724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen    static const int64_t delta = (((66 * 365 + 17) * 24) * 3600);
7913724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen    if (time_1904 < INT64_MIN + delta) {
7923724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen        return false;
7933724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen    }
7943724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen    time_t time_1970 = time_1904 - delta;
79572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
79672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    char tmp[32];
7973724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen    struct tm* tm = gmtime(&time_1970);
7983724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen    if (tm != NULL &&
7993724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen            strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", tm) > 0) {
8003724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen        s->setTo(tmp);
8013724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen        return true;
8023724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen    }
8033724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen    return false;
80472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
80572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
806c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
807ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar    ALOGV("entering parseChunk %lld/%d", (long long)*offset, depth);
808452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen
809452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen    if (*offset < 0) {
810452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen        ALOGE("b/23540914");
811452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen        return ERROR_MALFORMED;
812452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen    }
81320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t hdr[2];
81434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
81520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_IO;
81620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
81720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint64_t chunk_size = ntohl(hdr[0]);
8182d0ac425564ff9882ebaac5267d1a04d4af67d00Bernhard Rosenkränzer    int32_t chunk_type = ntohl(hdr[1]);
819c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t data_offset = *offset + 8;
82020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
82120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (chunk_size == 1) {
82234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
82320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_IO;
82420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
82520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        chunk_size = ntoh64(chunk_size);
82620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        data_offset += 8;
82771b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber
82871b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        if (chunk_size < 16) {
82971b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber            // The smallest valid chunk is 16 bytes long in this case.
83071b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber            return ERROR_MALFORMED;
83171b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        }
832a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen    } else if (chunk_size == 0) {
833a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen        if (depth == 0) {
834a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            // atom extends to end of file
835a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            off64_t sourceSize;
836a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            if (mDataSource->getSize(&sourceSize) == OK) {
837a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen                chunk_size = (sourceSize - *offset);
838a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            } else {
839a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen                // XXX could we just pick a "sufficiently large" value here?
840a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen                ALOGE("atom size is 0, and data source has no size");
841a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen                return ERROR_MALFORMED;
842a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            }
843a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen        } else {
844a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            // not allowed for non-toplevel atoms, skip it
845a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            *offset += 4;
846a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            return OK;
847a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen        }
84871b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber    } else if (chunk_size < 8) {
84971b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        // The smallest valid chunk is 8 bytes long.
850a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGE("invalid chunk size: %" PRIu64, chunk_size);
85171b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        return ERROR_MALFORMED;
85220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
85320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
85420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    char chunk[5];
85520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MakeFourCCString(chunk_type, chunk);
856ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar    ALOGV("chunk: %s @ %lld, %d", chunk, (long long)*offset, depth);
85720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
858b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    if (kUseHexDump) {
859b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        static const char kWhitespace[] = "                                        ";
860b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
861b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        printf("%sfound chunk '%s' of size %" PRIu64 "\n", indent, chunk, chunk_size);
86220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
863b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        char buffer[256];
864b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        size_t n = chunk_size;
865b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        if (n > sizeof(buffer)) {
866b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe            n = sizeof(buffer);
867b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        }
868b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        if (mDataSource->readAt(*offset, buffer, n)
869b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                < (ssize_t)n) {
870b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe            return ERROR_IO;
871b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        }
872ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
873b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        hexdump(buffer, n);
874b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    }
87520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
87672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder autoAdder(&mPath, chunk_type);
87772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
878452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen    // (data_offset - *offset) is either 8 or 16
879452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen    off64_t chunk_data_size = chunk_size - (data_offset - *offset);
880452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen    if (chunk_data_size < 0) {
881452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen        ALOGE("b/23540914");
882452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen        return ERROR_MALFORMED;
883452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen    }
8842fae4e4cb6b3039f28810e827de75b0612fadd83Marco Nelissen    if (chunk_type != FOURCC('m', 'd', 'a', 't') && chunk_data_size > kMaxAtomSize) {
8852fae4e4cb6b3039f28810e827de75b0612fadd83Marco Nelissen        char errMsg[100];
8862fae4e4cb6b3039f28810e827de75b0612fadd83Marco Nelissen        sprintf(errMsg, "%s atom has size %" PRId64, chunk, chunk_data_size);
8872fae4e4cb6b3039f28810e827de75b0612fadd83Marco Nelissen        ALOGE("%s (b/28615448)", errMsg);
8882fae4e4cb6b3039f28810e827de75b0612fadd83Marco Nelissen        android_errorWriteWithInfoLog(0x534e4554, "28615448", -1, errMsg, strlen(errMsg));
8892fae4e4cb6b3039f28810e827de75b0612fadd83Marco Nelissen        return ERROR_MALFORMED;
8902fae4e4cb6b3039f28810e827de75b0612fadd83Marco Nelissen    }
89120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
89272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (chunk_type != FOURCC('c', 'p', 'r', 't')
893515e855eae78aa495da58356486aaa666cb57fd1James Dong            && chunk_type != FOURCC('c', 'o', 'v', 'r')
89472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            && mPath.size() == 5 && underMetaDataPath(mPath)) {
895c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t stop_offset = *offset + chunk_size;
89672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        *offset = data_offset;
89772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        while (*offset < stop_offset) {
89872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            status_t err = parseChunk(offset, depth + 1);
89972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (err != OK) {
90072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return err;
90172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
90272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
903bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
904bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (*offset != stop_offset) {
905bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
906bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
90772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
90872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return OK;
90972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
91072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
91120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch(chunk_type) {
91220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'v'):
91320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'k'):
91420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'i', 'a'):
91520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'i', 'n', 'f'):
91620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('d', 'i', 'n', 'f'):
91720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'b', 'l'):
91820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'v', 'e', 'x'):
91920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'f'):
92020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'f'):
92120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'f', 'r', 'a'):
92272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('u', 'd', 't', 'a'):
92372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('i', 'l', 's', 't'):
924ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'i', 'n', 'f'):
925ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'c', 'h', 'i'):
9260a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        case FOURCC('e', 'd', 't', 's'):
92720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
928928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang            if (chunk_type == FOURCC('m', 'o', 'o', 'f') && !mMoofFound) {
929928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang                // store the offset of the first segment
930928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang                mMoofFound = true;
931928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang                mMoofOffset = *offset;
932928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang            }
933928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang
93450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
935a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                ALOGV("sampleTable chunk is %" PRIu64 " bytes long.", chunk_size);
93650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
937b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                if (mDataSource->flags()
938b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                        & (DataSource::kWantsPrefetching
939b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                            | DataSource::kIsCachingDataSource)) {
94050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    sp<MPEG4DataSource> cachedSource =
94150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                        new MPEG4DataSource(mDataSource);
94250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
94350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
94450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                        mDataSource = cachedSource;
94550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    }
94650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                }
9471edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber
948f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                if (mLastTrack == NULL)
949f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                    return ERROR_MALFORMED;
950f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
9511edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber                mLastTrack->sampleTable = new SampleTable(mDataSource);
95250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            }
95350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
9546f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber            bool isTrack = false;
955bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (chunk_type == FOURCC('t', 'r', 'a', 'k')) {
9566f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                isTrack = true;
9576f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
958bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                Track *track = new Track;
959bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->next = NULL;
960bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                if (mLastTrack) {
961bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    mLastTrack->next = track;
962bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                } else {
963bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    mFirstTrack = track;
964bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                }
965bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                mLastTrack = track;
966bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
967bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->meta = new MetaData;
968bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->includes_expensive_metadata = false;
9696f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                track->skipTrack = false;
970bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->timescale = 0;
971bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->meta->setCString(kKeyMIMEType, "application/octet-stream");
972bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
973bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
974c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
97520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset;
97620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
97720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
97820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
97920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
98020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
98120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
98220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
983bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
984bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
985bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
986bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
9876f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber            if (isTrack) {
9880386c91b8a910a134e5898ffa924c1b6c7560b13Wei Jia                int32_t trackId;
9890386c91b8a910a134e5898ffa924c1b6c7560b13Wei Jia                // There must be exact one track header per track.
9900386c91b8a910a134e5898ffa924c1b6c7560b13Wei Jia                if (!mLastTrack->meta->findInt32(kKeyTrackID, &trackId)) {
9910386c91b8a910a134e5898ffa924c1b6c7560b13Wei Jia                    mLastTrack->skipTrack = true;
9920386c91b8a910a134e5898ffa924c1b6c7560b13Wei Jia                }
9936f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                if (mLastTrack->skipTrack) {
9946f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    Track *cur = mFirstTrack;
9956f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
9966f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    if (cur == mLastTrack) {
9976f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        delete cur;
9986f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        mFirstTrack = mLastTrack = NULL;
9996f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    } else {
10006f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        while (cur && cur->next != mLastTrack) {
10016f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                            cur = cur->next;
10026f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        }
10036f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        cur->next = NULL;
10046f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        delete mLastTrack;
10056f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        mLastTrack = cur;
10066f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    }
10076f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
10086f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    return OK;
10096f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                }
10106f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
1011bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                status_t err = verifyTrack(mLastTrack);
1012bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1013bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                if (err != OK) {
1014bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    return err;
1015bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                }
1016bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
1017bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                mInitCheck = OK;
101820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1019dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                if (!mIsDrm) {
1020dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return UNKNOWN_ERROR;  // Return a dummy error.
1021dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                } else {
1022dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return OK;
1023dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
102420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
102520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
102620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
102720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10280a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        case FOURCC('e', 'l', 's', 't'):
10290a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        {
10300517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
10310517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
10320a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            // See 14496-12 8.6.6
10330a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            uint8_t version;
10340a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (mDataSource->readAt(data_offset, &version, 1) < 1) {
10350a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                return ERROR_IO;
10360a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
10370a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
10380a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            uint32_t entry_count;
10390a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (!mDataSource->getUInt32(data_offset + 4, &entry_count)) {
10400a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                return ERROR_IO;
10410a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
10420a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
10430a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (entry_count != 1) {
10440a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                // we only support a single entry at the moment, for gapless playback
10450a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                ALOGW("ignoring edit list with %d entries", entry_count);
1046fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            } else if (mHeaderTimescale == 0) {
1047210efd48ed21ca0084d9440f9a1db7d9878f8094Marco Nelissen                ALOGW("ignoring edit list because timescale is 0");
10480a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            } else {
10490a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                off64_t entriesoffset = data_offset + 8;
10500a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                uint64_t segment_duration;
10510a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int64_t media_time;
10520a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
10530a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                if (version == 1) {
10540a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    if (!mDataSource->getUInt64(entriesoffset, &segment_duration) ||
10550a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                            !mDataSource->getUInt64(entriesoffset + 8, (uint64_t*)&media_time)) {
10560a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        return ERROR_IO;
10570a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    }
10580a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                } else if (version == 0) {
10590a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    uint32_t sd;
10600a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int32_t mt;
10610a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    if (!mDataSource->getUInt32(entriesoffset, &sd) ||
10620a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                            !mDataSource->getUInt32(entriesoffset + 4, (uint32_t*)&mt)) {
10630a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        return ERROR_IO;
10640a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    }
10650a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    segment_duration = sd;
10660a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    media_time = mt;
10670a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                } else {
10680a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    return ERROR_IO;
10690a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                }
10700a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
1071fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                uint64_t halfscale = mHeaderTimescale / 2;
1072fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                segment_duration = (segment_duration * 1000000 + halfscale)/ mHeaderTimescale;
1073fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                media_time = (media_time * 1000000 + halfscale) / mHeaderTimescale;
10740a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
10750a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int64_t duration;
10760a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int32_t samplerate;
10771391f933b49cfb56da9aa63f723de83b076cf888Robert Shih                if (!mLastTrack) {
10781391f933b49cfb56da9aa63f723de83b076cf888Robert Shih                    return ERROR_MALFORMED;
10791391f933b49cfb56da9aa63f723de83b076cf888Robert Shih                }
10800a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                if (mLastTrack->meta->findInt64(kKeyDuration, &duration) &&
10810a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        mLastTrack->meta->findInt32(kKeySampleRate, &samplerate)) {
10820a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
10830a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t delay = (media_time  * samplerate + 500000) / 1000000;
10840a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
10850a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
1086608fe1d6b2ea4d88245a109afe2bfba580881a16Wei Jia                    int64_t paddingus = duration - (int64_t)(segment_duration + media_time);
1087465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                    if (paddingus < 0) {
1088465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        // track duration from media header (which is what kKeyDuration is) might
1089465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        // be slightly shorter than the segment duration, which would make the
1090465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        // padding negative. Clamp to zero.
1091465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        paddingus = 0;
1092465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                    }
10930a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t paddingsamples = (paddingus * samplerate + 500000) / 1000000;
10940a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    mLastTrack->meta->setInt32(kKeyEncoderPadding, paddingsamples);
10950a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                }
10960a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
10970a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            break;
10980a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        }
10990a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
1100ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('f', 'r', 'm', 'a'):
1101ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
11020517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
11030517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
110448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t original_fourcc;
1105ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset, &original_fourcc, 4) < 4) {
1106ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1107ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1108ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            original_fourcc = ntohl(original_fourcc);
1109ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("read original format: %d", original_fourcc);
1110f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
1111f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1112f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1113f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
1114ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc));
111548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t num_channels = 0;
111648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t sample_rate = 0;
111748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (AdjustChannelsAndRate(original_fourcc, &num_channels, &sample_rate)) {
111848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
111948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
112048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            }
1121ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1122ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1123ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1124ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('t', 'e', 'n', 'c'):
1125ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
11260517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
11270517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1128ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (chunk_size < 32) {
1129ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1130ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1131ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1132ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // tenc box contains 1 byte version, 3 byte flags, 3 byte default algorithm id, one byte
1133ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // default IV size, 16 bytes default KeyID
1134ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // (ISO 23001-7)
1135ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            char buf[4];
1136ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memset(buf, 0, 4);
1137ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 4, buf + 1, 3) < 3) {
1138ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1139ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1140ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t defaultAlgorithmId = ntohl(*((int32_t*)buf));
1141ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (defaultAlgorithmId > 1) {
1142ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only 0 (clear) and 1 (AES-128) are valid
1143ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1144ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1145ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1146ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memset(buf, 0, 4);
1147ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 7, buf + 3, 1) < 1) {
1148ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1149ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1150ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t defaultIVSize = ntohl(*((int32_t*)buf));
1151ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1152ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((defaultAlgorithmId == 0 && defaultIVSize != 0) ||
1153ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    (defaultAlgorithmId != 0 && defaultIVSize == 0)) {
1154ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only unencrypted data must have 0 IV size
1155ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1156ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            } else if (defaultIVSize != 0 &&
1157ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    defaultIVSize != 8 &&
1158ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    defaultIVSize != 16) {
1159ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only supported sizes are 0, 8 and 16
1160ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1161ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1162ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1163ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint8_t defaultKeyId[16];
1164ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1165ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 8, &defaultKeyId, 16) < 16) {
1166ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1167ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1168ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1169f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1170f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1171f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
1172ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setInt32(kKeyCryptoMode, defaultAlgorithmId);
1173ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setInt32(kKeyCryptoDefaultIVSize, defaultIVSize);
1174ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setData(kKeyCryptoKey, 'tenc', defaultKeyId, 16);
1175ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1176ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1177ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
117820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'k', 'h', 'd'):
117920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
11800517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
11810517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1182ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            status_t err;
1183ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) {
1184ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber                return err;
118520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
118620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
118720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
118820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
118920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1190ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('p', 's', 's', 'h'):
1191ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
11920517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
11930517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1194ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            PsshInfo pssh;
1195ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1196ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 4, &pssh.uuid, 16) < 16) {
1197ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1198ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1199ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1200ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t psshdatalen = 0;
1201ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 20, &psshdatalen, 4) < 4) {
1202ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1203ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1204ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            pssh.datalen = ntohl(psshdatalen);
1205ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("pssh data size: %d", pssh.datalen);
1206c9b255b7f771f55462cadd34e109bfee3bf80a3aMarco Nelissen            if (chunk_size < 20 || pssh.datalen > chunk_size - 20) {
1207ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // pssh data length exceeds size of containing box
1208ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1209ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1210ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
12118da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            pssh.data = new (std::nothrow) uint8_t[pssh.datalen];
12128da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            if (pssh.data == NULL) {
12138da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen                return ERROR_MALFORMED;
12148da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            }
1215ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("allocated pssh @ %p", pssh.data);
1216ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ssize_t requested = (ssize_t) pssh.datalen;
1217ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 24, pssh.data, requested) < requested) {
1218ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1219ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1220ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mPssh.push_back(pssh);
1221ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1222ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1223ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1224ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
122520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'h', 'd'):
122620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
12270517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
12280517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1229202fbed96db40ec5fb43d633fc97601a15a6dd7aRobert Shih            if (chunk_data_size < 4 || mLastTrack == NULL) {
123020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
123120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
123220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
123320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t version;
123434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
123520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, &version, sizeof(version))
123620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(version)) {
123720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
123820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
123920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1240c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t timescale_offset;
124120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
124220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
124320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 16;
124420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else if (version == 0) {
124520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 8;
124620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
124720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
124820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
124920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
125020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t timescale;
125134769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
125220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        timescale_offset, &timescale, sizeof(timescale))
125320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(timescale)) {
125420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
125520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
125620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12572e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang            if (!timescale) {
12582e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang                ALOGE("timescale should not be ZERO.");
12592e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang                return ERROR_MALFORMED;
12602e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang            }
12612e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang
126220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->timescale = ntohl(timescale);
126320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1264c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            // 14496-12 says all ones means indeterminate, but some files seem to use
1265c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            // 0 instead. We treat both the same.
126605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            int64_t duration = 0;
126720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
126834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
126920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration, sizeof(duration))
127020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration)) {
127120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
127220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
1273c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (duration != -1) {
1274c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    duration = ntoh64(duration);
1275c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
127620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
127705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t duration32;
127834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
127920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration32, sizeof(duration32))
128020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration32)) {
128120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
128220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
128305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (duration32 != 0xffffffff) {
128405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    duration = ntohl(duration32);
128505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
128620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1287e3e82d54c51a3130badcd9e433fe808d965f15c2Joshua J. Drake            if (duration != 0 && mLastTrack->timescale != 0) {
1288c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mLastTrack->meta->setInt64(
1289c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                        kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
1290c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
129120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12927a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            uint8_t lang[2];
12937a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            off64_t lang_offset;
12947a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            if (version == 1) {
12957a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                lang_offset = timescale_offset + 4 + 8;
12967a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            } else if (version == 0) {
12977a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                lang_offset = timescale_offset + 4 + 4;
12987a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            } else {
12997a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                return ERROR_IO;
13007a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            }
13017a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
13027a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            if (mDataSource->readAt(lang_offset, &lang, sizeof(lang))
13037a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                    < (ssize_t)sizeof(lang)) {
13047a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                return ERROR_IO;
13057a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            }
13067a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
13077a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // To get the ISO-639-2/T three character language code
13087a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // 1 bit pad followed by 3 5-bits characters. Each character
13097a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // is packed as the difference between its ASCII value and 0x60.
13107a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            char lang_code[4];
13117a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[0] = ((lang[0] >> 2) & 0x1f) + 0x60;
13127a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[1] = ((lang[0] & 0x3) << 3 | (lang[1] >> 5)) + 0x60;
13137a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[2] = (lang[1] & 0x1f) + 0x60;
13147a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[3] = '\0';
13157a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
13167a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            mLastTrack->meta->setCString(
13177a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                    kKeyMediaLanguage, lang_code);
13187a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
131920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
132020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
132120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
132220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'd'):
132320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
132420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 8) {
132520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
132620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
132720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
132820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8];
1329c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size < (off64_t)sizeof(buffer)) {
1330bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1331bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
1332bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
133334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
133420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, 8) < 8) {
133520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
133620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
133720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
133820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
133920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
134020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
134120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
134220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
134320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t entry_count = U32_AT(&buffer[4]);
134420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
134520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (entry_count > 1) {
13463b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // For 3GPP timed text, there could be multiple tx3g boxes contain
13473b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // multiple text display formats. These formats will be used to
13483b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // display the timed text.
1349ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // For encrypted files, there may also be more than one entry.
13503b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                const char *mime;
1351f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
1352f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                if (mLastTrack == NULL)
1353f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                    return ERROR_MALFORMED;
1354f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
13553b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1356ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) &&
1357ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                        strcasecmp(mime, "application/octet-stream")) {
13583b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    // For now we only support a single type of media per track.
13593b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    mLastTrack->skipTrack = true;
13603b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    *offset += chunk_size;
13613b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    break;
13623b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                }
136320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1364c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
136520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + 8;
136620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            for (uint32_t i = 0; i < entry_count; ++i) {
136720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
136820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
136920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
137020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
137120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1372bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1373bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1374bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1375bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
137620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
137720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
137820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
137920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
138048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        case FOURCC('e', 'n', 'c', 'a'):
138120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
1382371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
138320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
138420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8 + 20];
138520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
138620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic AudioSampleEntry size.
138720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
138820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
138920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
139034769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
139120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
139220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
139320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
139420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1395b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe            uint16_t data_ref_index __unused = U16_AT(&buffer[6]);
139648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t num_channels = U16_AT(&buffer[16]);
139720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
139881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint16_t sample_size = U16_AT(&buffer[18]);
139981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
140081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
1401f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1402f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1403f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
140448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (chunk_type != FOURCC('e', 'n', 'c', 'a')) {
140548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                // if the chunk type is enca, we'll get the type from the sinf/frma box later
140648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
140748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate);
140820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
140948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            ALOGV("*** coding='%s' %d channels, size %d, rate %d\n",
141081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                   chunk, num_channels, sample_size, sample_rate);
141120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
141220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
141320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1414c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
141520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
141620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
141720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
141820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
141920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
142020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
142120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1422bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1423bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1424bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1425bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
142620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
142720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
142820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
142920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
1430ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('e', 'n', 'c', 'v'):
143120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
1432e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('H', '2', '6', '3'):
1433e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('h', '2', '6', '3'):
143420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
14353b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'v', 'c', '1'):
14363b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'e', 'v', '1'):
143720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
14387be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber            mHasVideo = true;
14397be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
144020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[78];
144120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
144220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic VideoSampleEntry size.
144320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
144420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
144520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
144634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
144720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
144820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
144920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
145020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1451b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe            uint16_t data_ref_index __unused = U16_AT(&buffer[6]);
145220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t width = U16_AT(&buffer[6 + 18]);
145320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t height = U16_AT(&buffer[6 + 20]);
145420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1455ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // The video sample is not standard-compliant if it has invalid dimension.
1456a6256238d9015c42129fe43791968768fe501efaJames Dong            // Use some default width and height value, and
1457a6256238d9015c42129fe43791968768fe501efaJames Dong            // let the decoder figure out the actual width and height (and thus
1458a6256238d9015c42129fe43791968768fe501efaJames Dong            // be prepared for INFO_FOMRAT_CHANGED event).
1459a6256238d9015c42129fe43791968768fe501efaJames Dong            if (width == 0)  width  = 352;
1460a6256238d9015c42129fe43791968768fe501efaJames Dong            if (height == 0) height = 288;
1461a6256238d9015c42129fe43791968768fe501efaJames Dong
1462134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            // printf("*** coding='%s' width=%d height=%d\n",
1463134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            //        chunk, width, height);
146420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1465f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1466f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1467f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
1468ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (chunk_type != FOURCC('e', 'n', 'c', 'v')) {
1469ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // if the chunk type is encv, we'll get the type from the sinf/frma box later
1470ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
1471ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
147220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyWidth, width);
147320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyHeight, height);
147420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1475c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
147620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
147720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
147820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
147920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
148020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
148120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
148220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1483bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1484bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1485bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1486bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
148720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
148820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
148920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
149020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'c', 'o'):
149120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('c', 'o', '6', '4'):
149220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1493274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
1494274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake                return ERROR_MALFORMED;
1495274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake
149620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
149720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setChunkOffsetParams(
149820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
149920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15000517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
15010517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
150220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
150320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
150420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
150520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
150620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
150720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
150820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
150920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'c'):
151020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1511274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
1512274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake                return ERROR_MALFORMED;
1513274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake
151420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
151520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleToChunkParams(
151620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
151720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15180517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
15190517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
152020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
152120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
152220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
152320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
152420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
152520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
152620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
152720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'z'):
152820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'z', '2'):
152920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1530274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
1531274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake                return ERROR_MALFORMED;
1532274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake
153320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
153420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleSizeParams(
153520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
153620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15370517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
15380517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
153920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
154020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
154120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
154220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1543738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            size_t max_size;
154449110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            err = mLastTrack->sampleTable->getMaxSampleSize(&max_size);
154549110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber
154649110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            if (err != OK) {
154749110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber                return err;
154849110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            }
1549738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber
155005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (max_size != 0) {
155105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // Assume that a given buffer only contains at most 10 chunks,
155205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // each chunk originally prefixed with a 2 byte length will
155305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
155405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // and thus will grow by 2 bytes per chunk.
1555beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                if (max_size > SIZE_MAX - 10 * 2) {
1556beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                    ALOGE("max sample size too big: %zu", max_size);
1557beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                    return ERROR_MALFORMED;
1558beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                }
155905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
156005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            } else {
156105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // No size was specified. Pick a conservatively large size.
1562beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                uint32_t width, height;
1563beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                if (!mLastTrack->meta->findInt32(kKeyWidth, (int32_t*)&width) ||
1564beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                    !mLastTrack->meta->findInt32(kKeyHeight,(int32_t*) &height)) {
156505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ALOGE("No width or height, assuming worst case 1080p");
1566f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    width = 1920;
1567f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    height = 1080;
1568beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                } else {
1569beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                    // A resolution was specified, check that it's not too big. The values below
1570beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                    // were chosen so that the calculations below don't cause overflows, they're
1571beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                    // not indicating that resolutions up to 32kx32k are actually supported.
1572beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                    if (width > 32768 || height > 32768) {
1573beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                        ALOGE("can't support %u x %u video", width, height);
1574beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                        return ERROR_MALFORMED;
1575beef7e58c1f1837bdaed6ac37414d8c48a133813Marco Nelissen                    }
157605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
1577f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar
15784256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen                const char *mime;
15794256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
158007b2fbfb40770f3be0f674596f2e51d257c6d2bdLajos Molnar                if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)
158107b2fbfb40770f3be0f674596f2e51d257c6d2bdLajos Molnar                        || !strcmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
158207b2fbfb40770f3be0f674596f2e51d257c6d2bdLajos Molnar                    // AVC & HEVC requires compression ratio of at least 2, and uses
1583f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // macroblocks
1584f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    max_size = ((width + 15) / 16) * ((height + 15) / 16) * 192;
1585f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                } else {
1586f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // For all other formats there is no minimum compression
1587f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // ratio. Use compression ratio of 1.
1588f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    max_size = width * height * 3 / 2;
158905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
1590f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size);
159105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
1592113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong
15934256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            // NOTE: setting another piece of metadata invalidates any pointers (such as the
15944256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            // mimetype) previously obtained, so don't cache them.
1595113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            const char *mime;
1596113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1597113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            // Calculate average frame rate.
1598113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            if (!strncasecmp("video/", mime, 6)) {
1599113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                size_t nSamples = mLastTrack->sampleTable->countSamples();
1600949d857ea24950ff920820b4ccf78133dcc737d1Marco Nelissen                if (nSamples == 0) {
1601949d857ea24950ff920820b4ccf78133dcc737d1Marco Nelissen                    int32_t trackId;
1602949d857ea24950ff920820b4ccf78133dcc737d1Marco Nelissen                    if (mLastTrack->meta->findInt32(kKeyTrackID, &trackId)) {
1603949d857ea24950ff920820b4ccf78133dcc737d1Marco Nelissen                        for (size_t i = 0; i < mTrex.size(); i++) {
1604949d857ea24950ff920820b4ccf78133dcc737d1Marco Nelissen                            Trex *t = &mTrex.editItemAt(i);
1605949d857ea24950ff920820b4ccf78133dcc737d1Marco Nelissen                            if (t->track_ID == (uint32_t) trackId) {
1606949d857ea24950ff920820b4ccf78133dcc737d1Marco Nelissen                                if (t->default_sample_duration > 0) {
1607949d857ea24950ff920820b4ccf78133dcc737d1Marco Nelissen                                    int32_t frameRate =
1608949d857ea24950ff920820b4ccf78133dcc737d1Marco Nelissen                                            mLastTrack->timescale / t->default_sample_duration;
1609949d857ea24950ff920820b4ccf78133dcc737d1Marco Nelissen                                    mLastTrack->meta->setInt32(kKeyFrameRate, frameRate);
1610949d857ea24950ff920820b4ccf78133dcc737d1Marco Nelissen                                }
1611949d857ea24950ff920820b4ccf78133dcc737d1Marco Nelissen                                break;
1612949d857ea24950ff920820b4ccf78133dcc737d1Marco Nelissen                            }
1613949d857ea24950ff920820b4ccf78133dcc737d1Marco Nelissen                        }
1614949d857ea24950ff920820b4ccf78133dcc737d1Marco Nelissen                    }
1615949d857ea24950ff920820b4ccf78133dcc737d1Marco Nelissen                } else {
1616949d857ea24950ff920820b4ccf78133dcc737d1Marco Nelissen                    int64_t durationUs;
1617949d857ea24950ff920820b4ccf78133dcc737d1Marco Nelissen                    if (mLastTrack->meta->findInt64(kKeyDuration, &durationUs)) {
1618949d857ea24950ff920820b4ccf78133dcc737d1Marco Nelissen                        if (durationUs > 0) {
1619949d857ea24950ff920820b4ccf78133dcc737d1Marco Nelissen                            int32_t frameRate = (nSamples * 1000000LL +
1620949d857ea24950ff920820b4ccf78133dcc737d1Marco Nelissen                                        (durationUs >> 1)) / durationUs;
1621949d857ea24950ff920820b4ccf78133dcc737d1Marco Nelissen                            mLastTrack->meta->setInt32(kKeyFrameRate, frameRate);
1622949d857ea24950ff920820b4ccf78133dcc737d1Marco Nelissen                        }
1623113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                    }
1624113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                }
1625113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            }
1626113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong
162720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
162820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
162920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
163020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 't', 's'):
163120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1632274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
1633274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake                return ERROR_MALFORMED;
1634274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake
16350517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
16360517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
163720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
163820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setTimeToSampleParams(
163920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
164020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
164120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
164220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
164320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
164420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
164520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
164620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
164720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
16484931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        case FOURCC('c', 't', 't', 's'):
16494931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        {
1650274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
1651274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake                return ERROR_MALFORMED;
1652274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake
16530517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
16540517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
16554931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            status_t err =
16564931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                mLastTrack->sampleTable->setCompositionTimeToSampleParams(
16574931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                        data_offset, chunk_data_size);
16584931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
16594931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            if (err != OK) {
16604931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                return err;
16614931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            }
16624931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
16634931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            break;
16644931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        }
16654931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
166620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 's'):
166720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1668274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
1669274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake                return ERROR_MALFORMED;
1670274f64c7d6367f13c7852256b10339a3b75529f2Joshua J. Drake
16710517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
16720517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
167320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
167420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSyncSampleParams(
167520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
167620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
167720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
167820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
167920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
168020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
168120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
168220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
168320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1684afd492436efc7f66b958da14659b52232efa5910Marco Nelissen        // \xA9xyz
1685e1b2ccf317301af42bb4b6631a3bcd7d8f519d00Chih-Hung Hsieh        case FOURCC(0xA9, 'x', 'y', 'z'):
16864948818cb91176df74c972ac27b2f392b5d148bcJames Dong        {
16870517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
16880517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1689afd492436efc7f66b958da14659b52232efa5910Marco Nelissen            // Best case the total data length inside "\xA9xyz" box
1690afd492436efc7f66b958da14659b52232efa5910Marco Nelissen            // would be 8, for instance "\xA9xyz" + "\x00\x04\x15\xc7" + "0+0/",
16914948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // where "\x00\x04" is the text string length with value = 4,
16924948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // "\0x15\xc7" is the language code = en, and "0+0" is a
16934948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // location (string) value with longitude = 0 and latitude = 0.
16944948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (chunk_data_size < 8) {
16954948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_MALFORMED;
16964948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
16974948818cb91176df74c972ac27b2f392b5d148bcJames Dong
16984948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Worst case the location string length would be 18,
16994948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // for instance +90.0000-180.0000, without the trailing "/" and
17004948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // the string length + language code.
17014948818cb91176df74c972ac27b2f392b5d148bcJames Dong            char buffer[18];
17024948818cb91176df74c972ac27b2f392b5d148bcJames Dong
17034948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Substracting 5 from the data size is because the text string length +
17044948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // language code takes 4 bytes, and the trailing slash "/" takes 1 byte.
17054948818cb91176df74c972ac27b2f392b5d148bcJames Dong            off64_t location_length = chunk_data_size - 5;
17064948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (location_length >= (off64_t) sizeof(buffer)) {
17074948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_MALFORMED;
17084948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
17094948818cb91176df74c972ac27b2f392b5d148bcJames Dong
17104948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (mDataSource->readAt(
17114948818cb91176df74c972ac27b2f392b5d148bcJames Dong                        data_offset + 4, buffer, location_length) < location_length) {
17124948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_IO;
17134948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
17144948818cb91176df74c972ac27b2f392b5d148bcJames Dong
17154948818cb91176df74c972ac27b2f392b5d148bcJames Dong            buffer[location_length] = '\0';
17164948818cb91176df74c972ac27b2f392b5d148bcJames Dong            mFileMetaData->setCString(kKeyLocation, buffer);
17174948818cb91176df74c972ac27b2f392b5d148bcJames Dong            break;
17184948818cb91176df74c972ac27b2f392b5d148bcJames Dong        }
17194948818cb91176df74c972ac27b2f392b5d148bcJames Dong
172020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('e', 's', 'd', 's'):
172120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
17220517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
17230517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
172420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
172520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
172620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
172720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
172820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[256];
1729c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size > (off64_t)sizeof(buffer)) {
173020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
173120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
173220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
173334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
173420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
173520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
173620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
173720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
173820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
173920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
174020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
174120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
174220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1743f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1744f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1745f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
174620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
174720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
174820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1749ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            if (mPath.size() >= 2
1750ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
1751ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // Information from the ESDS must be relied on for proper
1752ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // setup of sample rate and channel count for MPEG4 Audio.
1753ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // The generic header appears to only contain generic
1754ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // information...
1755ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1756ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio(
1757ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                        &buffer[4], chunk_data_size - 4);
1758ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1759ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                if (err != OK) {
1760ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    return err;
1761ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                }
1762ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            }
1763ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar            if (mPath.size() >= 2
1764ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                    && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'v')) {
1765ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                // Check if the video is MPEG2
1766ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                ESDS esds(&buffer[4], chunk_data_size - 4);
1767ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar
1768ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                uint8_t objectTypeIndication;
1769ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                if (esds.getObjectTypeIndication(&objectTypeIndication) == OK) {
1770ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                    if (objectTypeIndication >= 0x60 && objectTypeIndication <= 0x65) {
1771ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                        mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG2);
1772ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                    }
1773ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar                }
1774ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar            }
177520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
177620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
177720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
177846f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar        case FOURCC('b', 't', 'r', 't'):
177946f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar        {
178046f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar            *offset += chunk_size;
178146f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar
178246f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar            uint8_t buffer[12];
178346f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar            if (chunk_data_size != sizeof(buffer)) {
178446f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar                return ERROR_MALFORMED;
178546f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar            }
178646f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar
178746f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar            if (mDataSource->readAt(
178846f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar                    data_offset, buffer, chunk_data_size) < chunk_data_size) {
178946f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar                return ERROR_IO;
179046f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar            }
179146f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar
179246f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar            uint32_t maxBitrate = U32_AT(&buffer[4]);
179346f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar            uint32_t avgBitrate = U32_AT(&buffer[8]);
179446f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar            if (maxBitrate > 0 && maxBitrate < INT32_MAX) {
179546f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar                mLastTrack->meta->setInt32(kKeyMaxBitRate, (int32_t)maxBitrate);
179646f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar            }
179746f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar            if (avgBitrate > 0 && avgBitrate < INT32_MAX) {
179846f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar                mLastTrack->meta->setInt32(kKeyBitRate, (int32_t)avgBitrate);
179946f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar            }
180046f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar            break;
180146f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar        }
180246f80165c595d81dda68f8f3fea27f4fb04937ddLajos Molnar
180320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', 'C'):
180420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
18050517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
18060517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1807d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson            sp<ABuffer> buffer = new ABuffer(chunk_data_size);
180820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
18096a456937c0d42fd8617126afdbf9e41087cf3cbcMarco Nelissen            if (buffer->data() == NULL) {
18106a456937c0d42fd8617126afdbf9e41087cf3cbcMarco Nelissen                ALOGE("b/28471206");
18116a456937c0d42fd8617126afdbf9e41087cf3cbcMarco Nelissen                return NO_MEMORY;
18126a456937c0d42fd8617126afdbf9e41087cf3cbcMarco Nelissen            }
18136a456937c0d42fd8617126afdbf9e41087cf3cbcMarco Nelissen
181434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
1815d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson                        data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
181620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
181720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
181820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1819f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1820f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1821f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
182220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
1823d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson                    kKeyAVCC, kTypeAVCC, buffer->data(), chunk_data_size);
182420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
182520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
182620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
18273b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'v', 'c', 'C'):
18283b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        {
18293b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            sp<ABuffer> buffer = new ABuffer(chunk_data_size);
18303b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
18316a456937c0d42fd8617126afdbf9e41087cf3cbcMarco Nelissen            if (buffer->data() == NULL) {
18326a456937c0d42fd8617126afdbf9e41087cf3cbcMarco Nelissen                ALOGE("b/28471206");
18336a456937c0d42fd8617126afdbf9e41087cf3cbcMarco Nelissen                return NO_MEMORY;
18346a456937c0d42fd8617126afdbf9e41087cf3cbcMarco Nelissen            }
18356a456937c0d42fd8617126afdbf9e41087cf3cbcMarco Nelissen
18363b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            if (mDataSource->readAt(
18373b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar                        data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
18383b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar                return ERROR_IO;
18393b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            }
18403b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
1841f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1842f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1843f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
18443b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            mLastTrack->meta->setData(
18453b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar                    kKeyHVCC, kTypeHVCC, buffer->data(), chunk_data_size);
18463b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
18473b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            *offset += chunk_size;
18483b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            break;
18493b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        }
185020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1851244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        case FOURCC('d', '2', '6', '3'):
1852244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        {
18530517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
185417e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            /*
185517e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * d263 contains a fixed 7 bytes part:
185617e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   vendor - 4 bytes
185717e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   version - 1 byte
185817e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   level - 1 byte
185917e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   profile - 1 byte
186017e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * optionally, "d263" box itself may contain a 16-byte
186117e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * bit rate box (bitr)
186217e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   average bit rate - 4 bytes
186317e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   max bit rate - 4 bytes
186417e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             */
186517e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            char buffer[23];
186617e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            if (chunk_data_size != 7 &&
186717e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong                chunk_data_size != 23) {
1868ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar                ALOGE("Incorrect D263 box size %lld", (long long)chunk_data_size);
1869244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                return ERROR_MALFORMED;
1870244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            }
1871244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1872244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            if (mDataSource->readAt(
1873244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                    data_offset, buffer, chunk_data_size) < chunk_data_size) {
1874244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                return ERROR_IO;
1875244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            }
1876244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1877f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
1878f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
1879f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
1880244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size);
1881244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1882244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            break;
1883244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        }
1884244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
188572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'e', 't', 'a'):
188672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
18878cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            off64_t stop_offset = *offset + chunk_size;
18888cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            *offset = data_offset;
18898cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            bool isParsingMetaKeys = underQTMetaPath(mPath, 2);
18908cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            if (!isParsingMetaKeys) {
18918cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                uint8_t buffer[4];
18928cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                if (chunk_data_size < (off64_t)sizeof(buffer)) {
18938ee368522ca7df126033a05dc3c430182b4495c9Marco Nelissen                    *offset = stop_offset;
18948cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    return ERROR_MALFORMED;
18958cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                }
1896bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
18978cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                if (mDataSource->readAt(
18988cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                            data_offset, buffer, 4) < 4) {
18998ee368522ca7df126033a05dc3c430182b4495c9Marco Nelissen                    *offset = stop_offset;
19008cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    return ERROR_IO;
19018cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                }
190272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
19038cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                if (U32_AT(buffer) != 0) {
19048cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    // Should be version 0, flags 0.
1905ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
19068cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    // If it's not, let's assume this is one of those
19078cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    // apparently malformed chunks that don't have flags
19088cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    // and completely different semantics than what's
19098cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    // in the MPEG4 specs and skip it.
19108ee368522ca7df126033a05dc3c430182b4495c9Marco Nelissen                    *offset = stop_offset;
19118cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                    return OK;
19128cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                }
19138cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                *offset +=  sizeof(buffer);
191472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
191572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
191672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            while (*offset < stop_offset) {
191772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                status_t err = parseChunk(offset, depth + 1);
191872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
191972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
192072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
192172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
1922bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1923bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1924bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1925bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
192672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
192772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
192872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
19295d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('m', 'e', 'a', 'n'):
19305d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('n', 'a', 'm', 'e'):
193172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('d', 'a', 't', 'a'):
193272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
19330517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
19340517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
193572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mPath.size() == 6 && underMetaDataPath(mPath)) {
1936fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                status_t err = parseITunesMetaData(data_offset, chunk_data_size);
193772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
193872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
193972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
194072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
194172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
194272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
194372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
194472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
194572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
194672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'v', 'h', 'd'):
194772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
19480517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
19490517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1950c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (chunk_data_size < 32) {
195172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_MALFORMED;
195272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
195372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1954c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            uint8_t header[32];
195572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
195672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, header, sizeof(header))
195772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    < (ssize_t)sizeof(header)) {
195872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
195972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
196072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1961fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            uint64_t creationTime;
1962c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            uint64_t duration = 0;
196372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (header[0] == 1) {
196472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U64_AT(&header[4]);
1965fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                mHeaderTimescale = U32_AT(&header[20]);
1966c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                duration = U64_AT(&header[24]);
1967c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (duration == 0xffffffffffffffff) {
1968c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    duration = 0;
1969c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1970bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (header[0] != 0) {
1971bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
197272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            } else {
197372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U32_AT(&header[4]);
1974fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                mHeaderTimescale = U32_AT(&header[12]);
1975c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                uint32_t d32 = U32_AT(&header[16]);
1976c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (d32 == 0xffffffff) {
1977c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    d32 = 0;
1978c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1979c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                duration = d32;
1980c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
19813724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen            if (duration != 0 && mHeaderTimescale != 0 && duration < UINT64_MAX / 1000000) {
1982c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mFileMetaData->setInt64(kKeyDuration, duration * 1000000 / mHeaderTimescale);
198372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
198472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
198572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            String8 s;
19863724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen            if (convertTimeToDate(creationTime, &s)) {
19873724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen                mFileMetaData->setCString(kKeyDate, s.string());
19883724c1c9ab40ce2cc313686cd2532c79c025ca6aMarco Nelissen            }
198972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
199072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
199172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
199272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
199372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1994c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        case FOURCC('m', 'e', 'h', 'd'):
1995c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        {
1996c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            *offset += chunk_size;
1997c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1998c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (chunk_data_size < 8) {
1999c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_MALFORMED;
2000c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
2001c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
2002c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            uint8_t flags[4];
2003c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (mDataSource->readAt(
2004c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                        data_offset, flags, sizeof(flags))
2005c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    < (ssize_t)sizeof(flags)) {
2006c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_IO;
2007c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
2008c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
2009c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            uint64_t duration = 0;
2010c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (flags[0] == 1) {
2011c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                // 64 bit
2012c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (chunk_data_size < 12) {
2013c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    return ERROR_MALFORMED;
2014c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
2015c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mDataSource->getUInt64(data_offset + 4, &duration);
2016c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (duration == 0xffffffffffffffff) {
2017c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    duration = 0;
2018c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
2019c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            } else if (flags[0] == 0) {
2020c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                // 32 bit
2021c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                uint32_t d32;
2022c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mDataSource->getUInt32(data_offset + 4, &d32);
2023c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (d32 == 0xffffffff) {
2024c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    d32 = 0;
2025c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
2026c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                duration = d32;
2027c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            } else {
2028c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_MALFORMED;
2029c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
2030c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
2031e3e82d54c51a3130badcd9e433fe808d965f15c2Joshua J. Drake            if (duration != 0 && mHeaderTimescale != 0) {
2032c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mFileMetaData->setInt64(kKeyDuration, duration * 1000000 / mHeaderTimescale);
2033c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
2034c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
2035c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            break;
2036c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        }
2037c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
2038dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        case FOURCC('m', 'd', 'a', 't'):
2039dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        {
2040ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("mdat chunk, drm: %d", mIsDrm);
2041928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang
2042928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang            mMdatFound = true;
2043928da1e9631bc7f5a5484c4668646c161515aee6Chong Zhang
2044dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (!mIsDrm) {
2045dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                *offset += chunk_size;
2046dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                break;
2047dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
2048dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
2049dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (chunk_size < 8) {
2050dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
2051dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
2052dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
2053dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return parseDrmSINF(offset, data_offset);
2054dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
2055dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
20563b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        case FOURCC('h', 'd', 'l', 'r'):
20573b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        {
20580517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
20590517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
2060ef185e94ce624146e3b1f3cbdb2404e833a0f81dChong Zhang            if (underQTMetaPath(mPath, 3)) {
2061ef185e94ce624146e3b1f3cbdb2404e833a0f81dChong Zhang                break;
2062ef185e94ce624146e3b1f3cbdb2404e833a0f81dChong Zhang            }
2063ef185e94ce624146e3b1f3cbdb2404e833a0f81dChong Zhang
20643b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t buffer;
20653b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (mDataSource->readAt(
20663b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                        data_offset + 8, &buffer, 4) < 4) {
20673b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_IO;
20683b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
20693b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
20703b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type = ntohl(buffer);
20713b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            // For the 3GPP file format, the handler-type within the 'hdlr' box
2072e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            // shall be 'text'. We also want to support 'sbtl' handler type
2073e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            // for a practical reason as various MPEG4 containers use it.
2074e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            if (type == FOURCC('t', 'e', 'x', 't') || type == FOURCC('s', 'b', 't', 'l')) {
2075cf75af8f76265fb2909028f5dc68c7029dbe5f49Lajos Molnar                if (mLastTrack != NULL) {
2076cf75af8f76265fb2909028f5dc68c7029dbe5f49Lajos Molnar                    mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
2077cf75af8f76265fb2909028f5dc68c7029dbe5f49Lajos Molnar                }
20783b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
20793b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
20803b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            break;
20813b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        }
20823b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
20838cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        case FOURCC('k', 'e', 'y', 's'):
20848cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        {
20858cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            *offset += chunk_size;
20868cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
20878cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            if (underQTMetaPath(mPath, 3)) {
20888cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                parseQTMetaKey(data_offset, chunk_data_size);
20898cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            }
20908cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            break;
20918cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        }
20928cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
2093c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        case FOURCC('t', 'r', 'e', 'x'):
2094c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        {
2095c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            *offset += chunk_size;
2096c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
2097c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (chunk_data_size < 24) {
2098c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_IO;
2099c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
2100c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            Trex trex;
2101c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (!mDataSource->getUInt32(data_offset + 4, &trex.track_ID) ||
2102c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                !mDataSource->getUInt32(data_offset + 8, &trex.default_sample_description_index) ||
2103c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                !mDataSource->getUInt32(data_offset + 12, &trex.default_sample_duration) ||
2104c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                !mDataSource->getUInt32(data_offset + 16, &trex.default_sample_size) ||
2105c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                !mDataSource->getUInt32(data_offset + 20, &trex.default_sample_flags)) {
2106c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_IO;
2107c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
2108c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            mTrex.add(trex);
2109c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            break;
2110c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        }
2111c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
21127a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        case FOURCC('t', 'x', '3', 'g'):
21137a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        {
2114f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            if (mLastTrack == NULL)
2115f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                return ERROR_MALFORMED;
2116f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
21173b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type;
21183b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            const void *data;
21193b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            size_t size = 0;
21203b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (!mLastTrack->meta->findData(
21213b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    kKeyTextFormatData, &type, &data, &size)) {
21223b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                size = 0;
21233b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
21243b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
21250e20b2093aa2bbc93afed8d68d3765d18a431b74Nick Kralevich            if ((chunk_size > SIZE_MAX) || (SIZE_MAX - chunk_size <= size)) {
2126dc69f4856187904bfb0d12a72cdf5a563a0deff2Joshua J. Drake                return ERROR_MALFORMED;
2127dc69f4856187904bfb0d12a72cdf5a563a0deff2Joshua J. Drake            }
2128dc69f4856187904bfb0d12a72cdf5a563a0deff2Joshua J. Drake
21298da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            uint8_t *buffer = new (std::nothrow) uint8_t[size + chunk_size];
21308da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            if (buffer == NULL) {
21318da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen                return ERROR_MALFORMED;
21328da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            }
21333b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
21343b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (size > 0) {
21353b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                memcpy(buffer, data, size);
21363b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
21373b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
21383b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size))
21393b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    < chunk_size) {
21403b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                delete[] buffer;
21413b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                buffer = NULL;
21423b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
21430517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen                // advance read pointer so we don't end up reading this again
21440517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen                *offset += chunk_size;
21453b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_IO;
21463b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
21473b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
21483b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            mLastTrack->meta->setData(
21493b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    kKeyTextFormatData, 0, buffer, size + chunk_size);
21503b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
21513b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            delete[] buffer;
21527a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
21537a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            *offset += chunk_size;
21547a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            break;
21557a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        }
21567a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
2157515e855eae78aa495da58356486aaa666cb57fd1James Dong        case FOURCC('c', 'o', 'v', 'r'):
2158515e855eae78aa495da58356486aaa666cb57fd1James Dong        {
21590517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
21600517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
2161515e855eae78aa495da58356486aaa666cb57fd1James Dong            if (mFileMetaData != NULL) {
2162635bc8f90429b2fdcaf7f8d43f7f59bcd0fe951cDan Albert                ALOGV("chunk_data_size = %" PRId64 " and data_offset = %" PRId64,
2163635bc8f90429b2fdcaf7f8d43f7f59bcd0fe951cDan Albert                      chunk_data_size, data_offset);
21641e51401794ff830c912c21123c321b83c17b491dJoshua J. Drake
2165635bc8f90429b2fdcaf7f8d43f7f59bcd0fe951cDan Albert                if (chunk_data_size < 0 || static_cast<uint64_t>(chunk_data_size) >= SIZE_MAX - 1) {
21661e51401794ff830c912c21123c321b83c17b491dJoshua J. Drake                    return ERROR_MALFORMED;
21671e51401794ff830c912c21123c321b83c17b491dJoshua J. Drake                }
21681552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1);
21696a456937c0d42fd8617126afdbf9e41087cf3cbcMarco Nelissen                if (buffer->data() == NULL) {
21706a456937c0d42fd8617126afdbf9e41087cf3cbcMarco Nelissen                    ALOGE("b/28471206");
21716a456937c0d42fd8617126afdbf9e41087cf3cbcMarco Nelissen                    return NO_MEMORY;
21726a456937c0d42fd8617126afdbf9e41087cf3cbcMarco Nelissen                }
2173515e855eae78aa495da58356486aaa666cb57fd1James Dong                if (mDataSource->readAt(
21741552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                    data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) {
2175515e855eae78aa495da58356486aaa666cb57fd1James Dong                    return ERROR_IO;
2176515e855eae78aa495da58356486aaa666cb57fd1James Dong                }
2177515e855eae78aa495da58356486aaa666cb57fd1James Dong                const int kSkipBytesOfDataBox = 16;
217897d45dbfdfc9018f1cbf72641c1447ff59431ae3Joshua J. Drake                if (chunk_data_size <= kSkipBytesOfDataBox) {
217997d45dbfdfc9018f1cbf72641c1447ff59431ae3Joshua J. Drake                    return ERROR_MALFORMED;
218097d45dbfdfc9018f1cbf72641c1447ff59431ae3Joshua J. Drake                }
218197d45dbfdfc9018f1cbf72641c1447ff59431ae3Joshua J. Drake
2182515e855eae78aa495da58356486aaa666cb57fd1James Dong                mFileMetaData->setData(
2183515e855eae78aa495da58356486aaa666cb57fd1James Dong                    kKeyAlbumArt, MetaData::TYPE_NONE,
21841552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                    buffer->data() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox);
2185515e855eae78aa495da58356486aaa666cb57fd1James Dong            }
2186515e855eae78aa495da58356486aaa666cb57fd1James Dong
2187515e855eae78aa495da58356486aaa666cb57fd1James Dong            break;
2188515e855eae78aa495da58356486aaa666cb57fd1James Dong        }
2189515e855eae78aa495da58356486aaa666cb57fd1James Dong
219058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        case FOURCC('c', 'o', 'l', 'r'):
219158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        {
219258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            *offset += chunk_size;
219358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            // this must be in a VisualSampleEntry box under the Sample Description Box ('stsd')
219458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            // ignore otherwise
219558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            if (depth >= 2 && mPath[depth - 2] == FOURCC('s', 't', 's', 'd')) {
219658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar                status_t err = parseColorInfo(data_offset, chunk_data_size);
219758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar                if (err != OK) {
219858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar                    return err;
219958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar                }
220058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            }
220158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
220258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            break;
220358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        }
220458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
2205fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('t', 'i', 't', 'l'):
2206fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('p', 'e', 'r', 'f'):
2207fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'u', 't', 'h'):
2208fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('g', 'n', 'r', 'e'):
2209fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'l', 'b', 'm'):
2210fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('y', 'r', 'r', 'c'):
2211fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
22120517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
22130517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
2214fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            status_t err = parse3GPPMetaData(data_offset, chunk_data_size, depth);
2215fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2216fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (err != OK) {
2217fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                return err;
2218fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2219fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2220fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2221fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2222fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2223328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        case FOURCC('I', 'D', '3', '2'):
2224328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        {
22250517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
22260517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
2227328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            if (chunk_data_size < 6) {
2228328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                return ERROR_MALFORMED;
2229328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            }
2230328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2231328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            parseID3v2MetaData(data_offset + 6);
2232328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2233328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            break;
2234328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        }
2235328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
22365d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('-', '-', '-', '-'):
22375d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        {
22385d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentMean.clear();
22395d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentName.clear();
22405d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentData.clear();
22415d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            *offset += chunk_size;
22425d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            break;
22435d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        }
22445d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen
224505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('s', 'i', 'd', 'x'):
224605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        {
224705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            parseSegmentIndex(data_offset, chunk_data_size);
224805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset += chunk_size;
224905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return UNKNOWN_ERROR; // stop parsing after sidx
225005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
225105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
225220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
225320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
22548cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            // check if we're parsing 'ilst' for meta keys
22558cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            // if so, treat type as a number (key-id).
22568cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            if (underQTMetaPath(mPath, 3)) {
22578cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                parseQTMetaVal(chunk_type, data_offset, chunk_data_size);
22588cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            }
22598cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
226020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
226120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
226220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
226320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
226420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
226520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
226620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
226720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
226805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) {
226905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen  ALOGV("MPEG4Extractor::parseSegmentIndex");
227005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
227105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 12) {
227205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      return -EINVAL;
227305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
227405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
227505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
227605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) {
227705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
227805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
227905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
228005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t version = flags >> 24;
228105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    flags &= 0xffffff;
228205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
228305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx version %d", version);
228405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
228505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t referenceId;
228605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, &referenceId)) {
228705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
228805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
228905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
229005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t timeScale;
229105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 8, &timeScale)) {
229205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
229305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
229405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx refid/timescale: %d/%d", referenceId, timeScale);
2295e3e82d54c51a3130badcd9e433fe808d965f15c2Joshua J. Drake    if (timeScale == 0)
2296e3e82d54c51a3130badcd9e433fe808d965f15c2Joshua J. Drake        return ERROR_MALFORMED;
229705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
229805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t earliestPresentationTime;
229905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t firstOffset;
230005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
230105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 12;
230205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 12;
230305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
230405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (version == 0) {
230505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 8) {
230605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
230705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
230805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t tmp;
230905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
231005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
231105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
231205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        earliestPresentationTime = tmp;
231305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset + 4, &tmp)) {
231405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
231505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
231605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        firstOffset = tmp;
231705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 8;
231805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 8;
231905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
232005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 16) {
232105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
232205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
232305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset, &earliestPresentationTime)) {
232405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
232505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
232605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset + 8, &firstOffset)) {
232705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
232805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
232905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 16;
233005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 16;
233105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
2332a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("sidx pres/off: %" PRIu64 "/%" PRIu64, earliestPresentationTime, firstOffset);
233305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
233405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 4) {
233505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
233605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
233705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
233805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint16_t referenceCount;
233905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt16(offset + 2, &referenceCount)) {
234005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
234105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
234205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 4;
234305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 4;
234405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("refcount: %d", referenceCount);
234505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
234605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < referenceCount * 12) {
234705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
234805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
234905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
235005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t total_duration = 0;
235105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    for (unsigned int i = 0; i < referenceCount; i++) {
235205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t d1, d2, d3;
235305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
235405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &d1) ||     // size
235505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            !mDataSource->getUInt32(offset + 4, &d2) || // duration
235605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            !mDataSource->getUInt32(offset + 8, &d3)) { // flags
235705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
235805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
235905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
236005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (d1 & 0x80000000) {
236105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGW("sub-sidx boxes not supported yet");
236205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
236305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool sap = d3 & 0x80000000;
23643f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen        uint32_t saptype = (d3 >> 28) & 7;
23653f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen        if (!sap || (saptype != 1 && saptype != 2)) {
23663f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            // type 1 and 2 are sync samples
23673f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            ALOGW("not a stream access point, or unsupported type: %08x", d3);
236805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
236905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        total_duration += d2;
237005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 12;
237105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV(" item %d, %08x %08x %08x", i, d1, d2, d3);
237205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        SidxEntry se;
237305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        se.mSize = d1 & 0x7fffffff;
237405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        se.mDurationUs = 1000000LL * d2 / timeScale;
237505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mSidxEntries.add(se);
237605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
237705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2378c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    uint64_t sidxDuration = total_duration * 1000000 / timeScale;
237905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2380f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake    if (mLastTrack == NULL)
2381f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake        return ERROR_MALFORMED;
2382f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
238305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t metaDuration;
238405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mLastTrack->meta->findInt64(kKeyDuration, &metaDuration) || metaDuration == 0) {
2385c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        mLastTrack->meta->setInt64(kKeyDuration, sidxDuration);
238605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
238705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
238805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
238905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
23908cfad968d5ec429b033caff9743f1ef15090be61Chong Zhangstatus_t MPEG4Extractor::parseQTMetaKey(off64_t offset, size_t size) {
23918cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (size < 8) {
23928cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        return ERROR_MALFORMED;
23938cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
23948cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
23958cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    uint32_t count;
23968cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (!mDataSource->getUInt32(offset + 4, &count)) {
23978cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        return ERROR_MALFORMED;
23988cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
23998cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
24008cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (mMetaKeyMap.size() > 0) {
24018cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        ALOGW("'keys' atom seen again, discarding existing entries");
24028cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        mMetaKeyMap.clear();
24038cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
24048cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
24058cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    off64_t keyOffset = offset + 8;
24068cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    off64_t stopOffset = offset + size;
24078cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    for (size_t i = 1; i <= count; i++) {
24088cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        if (keyOffset + 8 > stopOffset) {
24098cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            return ERROR_MALFORMED;
24108cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        }
24118cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
24128cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        uint32_t keySize;
24138cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        if (!mDataSource->getUInt32(keyOffset, &keySize)
24148cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                || keySize < 8
24158cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                || keyOffset + keySize > stopOffset) {
24168cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            return ERROR_MALFORMED;
24178cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        }
24188cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
24198cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        uint32_t type;
24208cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        if (!mDataSource->getUInt32(keyOffset + 4, &type)
24218cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                || type != FOURCC('m', 'd', 't', 'a')) {
24228cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            return ERROR_MALFORMED;
24238cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        }
24248cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
24258cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        keySize -= 8;
24268cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        keyOffset += 8;
24278cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
24288cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        sp<ABuffer> keyData = new ABuffer(keySize);
24298cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        if (keyData->data() == NULL) {
24308cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            return ERROR_MALFORMED;
24318cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        }
24328cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        if (mDataSource->readAt(
24338cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang                keyOffset, keyData->data(), keySize) < (ssize_t) keySize) {
24348cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            return ERROR_MALFORMED;
24358cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        }
24368cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
24378cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        AString key((const char *)keyData->data(), keySize);
24388cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        mMetaKeyMap.add(i, key);
24398cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
24408cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        keyOffset += keySize;
24418cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
24428cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    return OK;
24438cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang}
24448cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
24458cfad968d5ec429b033caff9743f1ef15090be61Chong Zhangstatus_t MPEG4Extractor::parseQTMetaVal(
24468cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        int32_t keyId, off64_t offset, size_t size) {
24478cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    ssize_t index = mMetaKeyMap.indexOfKey(keyId);
24488cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (index < 0) {
24498cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        // corresponding key is not present, ignore
24508cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        return ERROR_MALFORMED;
24518cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
245205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
24538cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (size <= 16) {
24548cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        return ERROR_MALFORMED;
24558cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
24568cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    uint32_t dataSize;
24578cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (!mDataSource->getUInt32(offset, &dataSize)
24588cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            || dataSize > size || dataSize <= 16) {
24598cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        return ERROR_MALFORMED;
24608cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
24618cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    uint32_t atomFourCC;
24628cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (!mDataSource->getUInt32(offset + 4, &atomFourCC)
24638cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            || atomFourCC != FOURCC('d', 'a', 't', 'a')) {
24648cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        return ERROR_MALFORMED;
24658cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
24668cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    uint32_t dataType;
24678cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (!mDataSource->getUInt32(offset + 8, &dataType)
24688cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            || ((dataType & 0xff000000) != 0)) {
24698cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        // not well-known type
24708cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        return ERROR_MALFORMED;
24718cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
24728cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
24738cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    dataSize -= 16;
24748cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    offset += 16;
24758cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
24768cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    if (dataType == 23 && dataSize >= 4) {
24778cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        // BE Float32
24788cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        uint32_t val;
24798cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        if (!mDataSource->getUInt32(offset, &val)) {
24808cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            return ERROR_MALFORMED;
24818cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        }
24828cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        if (!strcasecmp(mMetaKeyMap[index].c_str(), "com.android.capture.fps")) {
24838cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang            mFileMetaData->setFloat(kKeyCaptureFramerate, *(float *)&val);
24848cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        }
24858cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    } else {
24868cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        // add more keys if needed
24878cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang        ALOGV("ignoring key: type %d, size %d", dataType, dataSize);
24888cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    }
24898cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang
24908cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang    return OK;
24918cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang}
249205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2493ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huberstatus_t MPEG4Extractor::parseTrackHeader(
2494c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t data_offset, off64_t data_size) {
2495ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (data_size < 4) {
2496ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_MALFORMED;
2497ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2498ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2499ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint8_t version;
2500ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (mDataSource->readAt(data_offset, &version, 1) < 1) {
2501ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_IO;
2502ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2503ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2504ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    size_t dynSize = (version == 1) ? 36 : 24;
2505ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2506ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint8_t buffer[36 + 60];
2507ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2508c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    if (data_size != (off64_t)dynSize + 60) {
2509ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_MALFORMED;
2510ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2511ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2512ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (mDataSource->readAt(
2513ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber                data_offset, buffer, data_size) < (ssize_t)data_size) {
2514ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_IO;
2515ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2516ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2517b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    uint64_t ctime __unused, mtime __unused, duration __unused;
2518ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t id;
2519ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2520ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (version == 1) {
2521ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        ctime = U64_AT(&buffer[4]);
2522ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mtime = U64_AT(&buffer[12]);
2523ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        id = U32_AT(&buffer[20]);
2524ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        duration = U64_AT(&buffer[28]);
252504022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen    } else if (version == 0) {
2526ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        ctime = U32_AT(&buffer[4]);
2527ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mtime = U32_AT(&buffer[8]);
2528ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        id = U32_AT(&buffer[12]);
2529ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        duration = U32_AT(&buffer[20]);
253004022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen    } else {
253104022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen        return ERROR_UNSUPPORTED;
2532ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2533ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2534f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake    if (mLastTrack == NULL)
2535f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake        return ERROR_MALFORMED;
2536f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
2537ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    mLastTrack->meta->setInt32(kKeyTrackID, id);
2538ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2539ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    size_t matrixOffset = dynSize + 16;
2540ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a00 = U32_AT(&buffer[matrixOffset]);
2541ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a01 = U32_AT(&buffer[matrixOffset + 4]);
2542ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a10 = U32_AT(&buffer[matrixOffset + 12]);
2543ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a11 = U32_AT(&buffer[matrixOffset + 16]);
2544ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2545ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#if 0
2546b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    int32_t dx = U32_AT(&buffer[matrixOffset + 8]);
2547b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    int32_t dy = U32_AT(&buffer[matrixOffset + 20]);
2548b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe
2549df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("x' = %.2f * x + %.2f * y + %.2f",
2550ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber         a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f);
2551df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("y' = %.2f * x + %.2f * y + %.2f",
2552ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber         a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f);
2553ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#endif
2554ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2555ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t rotationDegrees;
2556ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2557ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    static const int32_t kFixedOne = 0x10000;
2558ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) {
2559ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        // Identity, no rotation
2560ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 0;
2561ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) {
2562ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 90;
2563ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) {
2564ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 270;
2565ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) {
2566ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 180;
2567ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else {
25685ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("We only support 0,90,180,270 degree rotation matrices");
2569ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 0;
2570ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2571ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2572ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (rotationDegrees != 0) {
2573ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees);
2574ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2575ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2576b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    // Handle presentation display size, which could be different
2577b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    // from the image size indicated by kKeyWidth and kKeyHeight.
2578ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t width = U32_AT(&buffer[dynSize + 52]);
2579ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t height = U32_AT(&buffer[dynSize + 56]);
2580b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    mLastTrack->meta->setInt32(kKeyDisplayWidth, width >> 16);
2581b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    mLastTrack->meta->setInt32(kKeyDisplayHeight, height >> 16);
2582ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2583ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    return OK;
2584ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber}
2585ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2586fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhéstatus_t MPEG4Extractor::parseITunesMetaData(off64_t offset, size_t size) {
2587c570778430a22b5488cae72982cf9fb8033dbda3Nick Kralevich    if (size < 4 || size == SIZE_MAX) {
258872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_MALFORMED;
258972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
259072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
25918da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    uint8_t *buffer = new (std::nothrow) uint8_t[size + 1];
25928da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    if (buffer == NULL) {
25938da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        return ERROR_MALFORMED;
25948da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    }
259572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (mDataSource->readAt(
259672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                offset, buffer, size) != (ssize_t)size) {
259772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        delete[] buffer;
259872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        buffer = NULL;
259972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
260072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_IO;
260172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
260272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
260372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t flags = U32_AT(buffer);
260472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
260572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t metadataKey = 0;
26065d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    char chunk[5];
26075d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    MakeFourCCString(mPath[4], chunk);
2608ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar    ALOGV("meta: %s @ %lld", chunk, (long long)offset);
26092d0ac425564ff9882ebaac5267d1a04d4af67d00Bernhard Rosenkränzer    switch ((int32_t)mPath[4]) {
261072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'a', 'l', 'b'):
261172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
261272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbum;
261372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
261472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
261572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'A', 'R', 'T'):
261672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
261772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyArtist;
261872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
261972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
262066ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        case FOURCC('a', 'A', 'R', 'T'):
262166ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        {
262266ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            metadataKey = kKeyAlbumArtist;
262366ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            break;
262466ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        }
262572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'd', 'a', 'y'):
262672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
262772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyYear;
262872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
262972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
263072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'n', 'a', 'm'):
263172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
263272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyTitle;
263372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
263472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
263572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'w', 'r', 't'):
263672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
263772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyWriter;
263872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
263972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
264072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('c', 'o', 'v', 'r'):
264172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
264272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbumArt;
264372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
264472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
264572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('g', 'n', 'r', 'e'):
264672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
264772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyGenre;
264872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
264972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
265026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC(0xa9, 'g', 'e', 'n'):
265126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
265226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            metadataKey = kKeyGenre;
265326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
265426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
265511f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        case FOURCC('c', 'p', 'i', 'l'):
265611f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        {
265711f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            if (size == 9 && flags == 21) {
265811f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                char tmp[16];
265911f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                sprintf(tmp, "%d",
266011f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                        (int)buffer[size - 1]);
266111f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen
266211f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                mFileMetaData->setCString(kKeyCompilation, tmp);
266311f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            }
266411f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            break;
266511f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        }
266672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('t', 'r', 'k', 'n'):
266772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
266872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (size == 16 && flags == 0) {
266972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char tmp[16];
2670afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTrack = (uint16_t*)&buffer[10];
2671afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTotalTracks = (uint16_t*)&buffer[12];
2672afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                sprintf(tmp, "%d/%d", ntohs(*pTrack), ntohs(*pTotalTracks));
267372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
267472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
267572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
267672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
267772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
267826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC('d', 'i', 's', 'k'):
267926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
2680afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik            if ((size == 14 || size == 16) && flags == 0) {
268126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                char tmp[16];
2682afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pDisc = (uint16_t*)&buffer[10];
2683afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTotalDiscs = (uint16_t*)&buffer[12];
2684afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                sprintf(tmp, "%d/%d", ntohs(*pDisc), ntohs(*pTotalDiscs));
268526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
268626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(kKeyDiscNumber, tmp);
268726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            }
268826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
268926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
26905d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('-', '-', '-', '-'):
26915d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        {
26925d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            buffer[size] = '\0';
26935d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            switch (mPath[5]) {
26945d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('m', 'e', 'a', 'n'):
26955d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentMean.setTo((const char *)buffer + 4);
26965d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
26975d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('n', 'a', 'm', 'e'):
26985d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentName.setTo((const char *)buffer + 4);
26995d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
27005d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('d', 'a', 't', 'a'):
27015cae16bdce77b0a3ba590b55637f7d55a2f35402Wei Jia                    if (size < 8) {
27025cae16bdce77b0a3ba590b55637f7d55a2f35402Wei Jia                        delete[] buffer;
27035cae16bdce77b0a3ba590b55637f7d55a2f35402Wei Jia                        buffer = NULL;
27045cae16bdce77b0a3ba590b55637f7d55a2f35402Wei Jia                        ALOGE("b/24346430");
27055cae16bdce77b0a3ba590b55637f7d55a2f35402Wei Jia                        return ERROR_MALFORMED;
27065cae16bdce77b0a3ba590b55637f7d55a2f35402Wei Jia                    }
27075d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentData.setTo((const char *)buffer + 8);
27085d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
27095d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            }
27108c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
27118c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // Once we have a set of mean/name/data info, go ahead and process
27128c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // it to see if its something we are interested in.  Whether or not
27138c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // were are interested in the specific tag, make sure to clear out
27148c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // the set so we can be ready to process another tuple should one
27158c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // show up later in the file.
27168c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            if ((mLastCommentMean.length() != 0) &&
27178c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                (mLastCommentName.length() != 0) &&
27188c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                (mLastCommentData.length() != 0)) {
27198c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
27208c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                if (mLastCommentMean == "com.apple.iTunes"
27218c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        && mLastCommentName == "iTunSMPB") {
27228c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    int32_t delay, padding;
27238c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    if (sscanf(mLastCommentData,
27248c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                               " %*x %x %x %*x", &delay, &padding) == 2) {
2725f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                        if (mLastTrack == NULL)
2726f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake                            return ERROR_MALFORMED;
2727f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
27288c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
27298c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        mLastTrack->meta->setInt32(kKeyEncoderPadding, padding);
27308c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    }
27315d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                }
27328c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
27335d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentMean.clear();
27345d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentName.clear();
27355d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentData.clear();
27365d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            }
27375d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            break;
27385d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        }
273926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
274072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        default:
274172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
274272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
274372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
2744328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    if (size >= 8 && metadataKey && !mFileMetaData->hasData(metadataKey)) {
274572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        if (metadataKey == kKeyAlbumArt) {
274672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setData(
274772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    kKeyAlbumArt, MetaData::TYPE_NONE,
274872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    buffer + 8, size - 8);
274972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else if (metadataKey == kKeyGenre) {
275072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (flags == 0) {
275126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // uint8_t genre code, iTunes genre codes are
275226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // the standard id3 codes, except they start
275326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // at 1 instead of 0 (e.g. Pop is 14, not 13)
275426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // We use standard id3 numbering, so subtract 1.
275526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                int genrecode = (int)buffer[size - 1];
275626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                genrecode--;
275726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                if (genrecode < 0) {
275826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                    genrecode = 255; // reserved for 'unknown genre'
275926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                }
276072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char genre[10];
276126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                sprintf(genre, "%d", genrecode);
276272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
276372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(metadataKey, genre);
276426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            } else if (flags == 1) {
276526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // custom genre string
276626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                buffer[size] = '\0';
276726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
276826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(
276926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                        metadataKey, (const char *)buffer + 8);
277072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
277172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else {
277272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            buffer[size] = '\0';
277372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
277472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(
277572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    metadataKey, (const char *)buffer + 8);
277672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
277772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
277872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
277972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    delete[] buffer;
278072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    buffer = NULL;
278172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
278272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return OK;
278372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
278472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
278558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnarstatus_t MPEG4Extractor::parseColorInfo(off64_t offset, size_t size) {
278658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    if (size < 4 || size == SIZE_MAX || mLastTrack == NULL) {
278758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        return ERROR_MALFORMED;
278858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    }
278958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
279058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    uint8_t *buffer = new (std::nothrow) uint8_t[size + 1];
279158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    if (buffer == NULL) {
279258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        return ERROR_MALFORMED;
279358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    }
279458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    if (mDataSource->readAt(offset, buffer, size) != (ssize_t)size) {
279558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        delete[] buffer;
279658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        buffer = NULL;
279758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
279858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        return ERROR_IO;
279958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    }
280058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
280158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    int32_t type = U32_AT(&buffer[0]);
280258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    if ((type == FOURCC('n', 'c', 'l', 'x') && size >= 11)
280358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            || (type == FOURCC('n', 'c', 'l', 'c' && size >= 10))) {
280458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        int32_t primaries = U16_AT(&buffer[4]);
280558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        int32_t transfer = U16_AT(&buffer[6]);
280658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        int32_t coeffs = U16_AT(&buffer[8]);
280758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        bool fullRange = (type == FOURCC('n', 'c', 'l', 'x')) && (buffer[10] & 128);
280858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
280958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        ColorAspects aspects;
281058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        ColorUtils::convertIsoColorAspectsToCodecAspects(
281158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar                primaries, transfer, coeffs, fullRange, aspects);
281258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
281358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        // only store the first color specification
281458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        if (!mLastTrack->meta->hasData(kKeyColorPrimaries)) {
281558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            mLastTrack->meta->setInt32(kKeyColorPrimaries, aspects.mPrimaries);
281658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            mLastTrack->meta->setInt32(kKeyTransferFunction, aspects.mTransfer);
281758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            mLastTrack->meta->setInt32(kKeyColorMatrix, aspects.mMatrixCoeffs);
281858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            mLastTrack->meta->setInt32(kKeyColorRange, aspects.mRange);
281958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        }
282058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    }
282158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
282258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    delete[] buffer;
282358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    buffer = NULL;
282458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
282558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar    return OK;
282658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar}
282758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar
2828fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhéstatus_t MPEG4Extractor::parse3GPPMetaData(off64_t offset, size_t size, int depth) {
28295cea0155cfc41f67e91343c342f44251c03fde3aJoshua J. Drake    if (size < 4 || size == SIZE_MAX) {
2830fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        return ERROR_MALFORMED;
2831fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2832fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
28335cea0155cfc41f67e91343c342f44251c03fde3aJoshua J. Drake    uint8_t *buffer = new (std::nothrow) uint8_t[size + 1];
28348da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    if (buffer == NULL) {
28358da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        return ERROR_MALFORMED;
28368da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    }
2837fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    if (mDataSource->readAt(
2838fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                offset, buffer, size) != (ssize_t)size) {
2839fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        delete[] buffer;
2840fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        buffer = NULL;
2841fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2842fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        return ERROR_IO;
2843fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2844fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2845fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    uint32_t metadataKey = 0;
2846fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    switch (mPath[depth]) {
2847fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('t', 'i', 't', 'l'):
2848fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2849fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyTitle;
2850fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2851fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2852fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('p', 'e', 'r', 'f'):
2853fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2854fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyArtist;
2855fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2856fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2857fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'u', 't', 'h'):
2858fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2859fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyWriter;
2860fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2861fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2862fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('g', 'n', 'r', 'e'):
2863fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2864fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyGenre;
2865fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2866fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2867fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'l', 'b', 'm'):
2868fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2869fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (buffer[size - 1] != '\0') {
2870fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé              char tmp[4];
2871fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé              sprintf(tmp, "%u", buffer[size - 1]);
2872fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2873fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé              mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
2874fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2875fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2876fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyAlbum;
2877fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2878fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2879fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('y', 'r', 'r', 'c'):
2880fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2881fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            char tmp[5];
2882fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            uint16_t year = U16_AT(&buffer[4]);
2883fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2884fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (year < 10000) {
2885fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                sprintf(tmp, "%u", year);
2886fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2887fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                mFileMetaData->setCString(kKeyYear, tmp);
2888fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2889fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2890fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2891fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2892fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        default:
2893fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2894fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2895fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2896fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    if (metadataKey > 0) {
2897fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        bool isUTF8 = true; // Common case
2898fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        char16_t *framedata = NULL;
2899fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        int len16 = 0; // Number of UTF-16 characters
2900fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2901fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        // smallest possible valid UTF-16 string w BOM: 0xfe 0xff 0x00 0x00
29029458e715d391ee8fe455fc31f07ff35ce12e0531Joshua J. Drake        if (size < 6) {
29039458e715d391ee8fe455fc31f07ff35ce12e0531Joshua J. Drake            return ERROR_MALFORMED;
29049458e715d391ee8fe455fc31f07ff35ce12e0531Joshua J. Drake        }
29059458e715d391ee8fe455fc31f07ff35ce12e0531Joshua J. Drake
2906fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        if (size - 6 >= 4) {
2907fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            len16 = ((size - 6) / 2) - 1; // don't include 0x0000 terminator
2908fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            framedata = (char16_t *)(buffer + 6);
2909fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (0xfffe == *framedata) {
2910fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                // endianness marker (BOM) doesn't match host endianness
2911fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                for (int i = 0; i < len16; i++) {
2912fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                    framedata[i] = bswap_16(framedata[i]);
2913fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                }
2914fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                // BOM is now swapped to 0xfeff, we will execute next block too
2915fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2916fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2917fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (0xfeff == *framedata) {
2918fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                // Remove the BOM
2919fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                framedata++;
2920fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                len16--;
2921fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                isUTF8 = false;
2922fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2923fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // else normal non-zero-length UTF-8 string
2924fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // we can't handle UTF-16 without BOM as there is no other
2925fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // indication of encoding.
2926fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2927fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2928fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        if (isUTF8) {
29295cea0155cfc41f67e91343c342f44251c03fde3aJoshua J. Drake            buffer[size] = 0;
2930fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            mFileMetaData->setCString(metadataKey, (const char *)buffer + 6);
2931fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        } else {
2932fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // Convert from UTF-16 string to UTF-8 string.
2933fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            String8 tmpUTF8str(framedata, len16);
2934fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            mFileMetaData->setCString(metadataKey, tmpUTF8str.string());
2935fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2936fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2937fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2938fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    delete[] buffer;
2939fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    buffer = NULL;
2940fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2941fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    return OK;
2942fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé}
2943fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2944328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhévoid MPEG4Extractor::parseID3v2MetaData(off64_t offset) {
2945328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    ID3 id3(mDataSource, true /* ignorev1 */, offset);
2946328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2947328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    if (id3.isValid()) {
2948328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        struct Map {
2949328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            int key;
2950328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            const char *tag1;
2951328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            const char *tag2;
2952328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        };
2953328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        static const Map kMap[] = {
2954328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyAlbum, "TALB", "TAL" },
2955328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyArtist, "TPE1", "TP1" },
2956328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyAlbumArtist, "TPE2", "TP2" },
2957328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyComposer, "TCOM", "TCM" },
2958328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyGenre, "TCON", "TCO" },
2959328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyTitle, "TIT2", "TT2" },
2960328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyYear, "TYE", "TYER" },
2961328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyAuthor, "TXT", "TEXT" },
2962328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyCDTrackNumber, "TRK", "TRCK" },
2963328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyDiscNumber, "TPA", "TPOS" },
2964328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyCompilation, "TCP", "TCMP" },
2965328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        };
2966328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
2967328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2968328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        for (size_t i = 0; i < kNumMapEntries; ++i) {
2969328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            if (!mFileMetaData->hasData(kMap[i].key)) {
2970328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                ID3::Iterator *it = new ID3::Iterator(id3, kMap[i].tag1);
2971328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                if (it->done()) {
2972328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    delete it;
2973328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    it = new ID3::Iterator(id3, kMap[i].tag2);
2974328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                }
2975328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2976328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                if (it->done()) {
2977328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    delete it;
2978328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    continue;
2979328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                }
2980328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2981328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                String8 s;
2982328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                it->getString(&s);
2983328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                delete it;
2984328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2985328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                mFileMetaData->setCString(kMap[i].key, s);
2986328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            }
2987328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        }
2988328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2989328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        size_t dataSize;
2990328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        String8 mime;
2991328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        const void *data = id3.getAlbumArt(&dataSize, &mime);
2992328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2993328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        if (data) {
2994328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            mFileMetaData->setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize);
2995328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            mFileMetaData->setCString(kKeyAlbumArtMIME, mime.string());
2996328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        }
2997328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    }
2998328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé}
2999328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
3000b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissensp<IMediaSource> MPEG4Extractor::getTrack(size_t index) {
300120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
300220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
3003693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return NULL;
300420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
300520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
300620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
300720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
300820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
3009693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber            return NULL;
301020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
301120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
301220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
301320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
301420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
301520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3016371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
3017371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
3018371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
3019371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
3020c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
3021c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    Trex *trex = NULL;
3022c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    int32_t trackId;
3023c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    if (track->meta->findInt32(kKeyTrackID, &trackId)) {
3024c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        for (size_t i = 0; i < mTrex.size(); i++) {
3025949d857ea24950ff920820b4ccf78133dcc737d1Marco Nelissen            Trex *t = &mTrex.editItemAt(i);
3026c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (t->track_ID == (uint32_t) trackId) {
3027c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                trex = t;
3028c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                break;
3029c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
3030c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        }
30310386c91b8a910a134e5898ffa924c1b6c7560b13Wei Jia    } else {
30320386c91b8a910a134e5898ffa924c1b6c7560b13Wei Jia        ALOGE("b/21657957");
30330386c91b8a910a134e5898ffa924c1b6c7560b13Wei Jia        return NULL;
3034c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    }
3035c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
3036a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("getTrack called, pssh: %zu", mPssh.size());
3037ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3038a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia    const char *mime;
3039a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia    if (!track->meta->findCString(kKeyMIMEType, &mime)) {
3040a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        return NULL;
3041a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia    }
3042a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia
3043a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
3044a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        uint32_t type;
3045a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        const void *data;
3046a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        size_t size;
3047a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        if (!track->meta->findData(kKeyAVCC, &type, &data, &size)) {
3048a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia            return NULL;
3049a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        }
3050a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia
3051a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        const uint8_t *ptr = (const uint8_t *)data;
3052a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia
3053a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        if (size < 7 || ptr[0] != 1) {  // configurationVersion == 1
3054a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia            return NULL;
3055a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        }
3056a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
3057a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        uint32_t type;
3058a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        const void *data;
3059a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        size_t size;
3060a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        if (!track->meta->findData(kKeyHVCC, &type, &data, &size)) {
3061a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia            return NULL;
3062a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        }
3063a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia
3064a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        const uint8_t *ptr = (const uint8_t *)data;
3065a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia
3066a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        if (size < 22 || ptr[0] != 1) {  // configurationVersion == 1
3067a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia            return NULL;
3068a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        }
3069a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia    }
3070a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia
3071942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    return new MPEG4Source(this,
307205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            track->meta, mDataSource, track->timescale, track->sampleTable,
3073c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            mSidxEntries, trex, mMoofOffset);
307420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
307520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3076bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber// static
3077bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) {
3078bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const char *mime;
3079bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    CHECK(track->meta->findCString(kKeyMIMEType, &mime));
3080bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
3081bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    uint32_t type;
3082bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const void *data;
3083bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    size_t size;
3084bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
3085bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyAVCC, &type, &data, &size)
3086bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeAVCC) {
3087bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
3088bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
30893b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
30903b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        if (!track->meta->findData(kKeyHVCC, &type, &data, &size)
30913b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar                    || type != kTypeHVCC) {
30923b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            return ERROR_MALFORMED;
30933b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        }
3094bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
3095ae0c0a17e824356eb55a6692ff8dee6cdc050401Harish Mahendrakar            || !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG2)
3096bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
3097bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyESDS, &type, &data, &size)
3098bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeESDS) {
3099bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
3100bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
3101bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    }
3102bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
3103ce171998009e1abcb0c718c0aee495fcd33645e2Robert Shih    if (track->sampleTable == NULL || !track->sampleTable->isValid()) {
3104169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        // Make sure we have all the metadata we need.
3105ce171998009e1abcb0c718c0aee495fcd33645e2Robert Shih        ALOGE("stbl atom missing/invalid.");
3106169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        return ERROR_MALFORMED;
3107169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber    }
3108169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber
31092e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang    if (track->timescale == 0) {
31102e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang        ALOGE("timescale invalid.");
31112e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang        return ERROR_MALFORMED;
31122e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang    }
31132e81b588f2cc54eaa4f9c83cce279589fb221523Dan Liang
3114bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    return OK;
3115bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber}
3116bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
3117f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivitypedef enum {
3118f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_NONE             = -1,
3119f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_NULL_OBJECT      = 0,
3120f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_MAIN         = 1, /**< Main profile                              */
3121f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_AAC_LC           = 2,   /**< Low Complexity object                     */
3122f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_SSR          = 3,
3123f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_LTP          = 4,
3124f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_SBR              = 5,
3125f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_SCAL         = 6,
3126f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_TWIN_VQ          = 7,
3127f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_CELP             = 8,
3128f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_HVXC             = 9,
3129f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_10          = 10, /**< (reserved)                                */
3130f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_11          = 11, /**< (reserved)                                */
3131f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_TTSI             = 12, /**< TTSI Object                               */
3132f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MAIN_SYNTH       = 13, /**< Main Synthetic object                     */
3133f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_WAV_TAB_SYNTH    = 14, /**< Wavetable Synthesis object                */
3134f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_GEN_MIDI         = 15, /**< General MIDI object                       */
3135f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ALG_SYNTH_AUD_FX = 16, /**< Algorithmic Synthesis and Audio FX object */
3136f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_AAC_LC        = 17,   /**< Error Resilient(ER) AAC Low Complexity    */
3137f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_18          = 18, /**< (reserved)                                */
3138f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_AAC_LTP       = 19, /**< Error Resilient(ER) AAC LTP object        */
3139f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_AAC_SCAL      = 20,   /**< Error Resilient(ER) AAC Scalable object   */
3140f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_TWIN_VQ       = 21, /**< Error Resilient(ER) TwinVQ object         */
3141f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_BSAC          = 22,   /**< Error Resilient(ER) BSAC object           */
3142f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_AAC_LD        = 23,   /**< Error Resilient(ER) AAC LowDelay object   */
3143f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_CELP          = 24, /**< Error Resilient(ER) CELP object           */
3144f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_HVXC          = 25, /**< Error Resilient(ER) HVXC object           */
3145f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_HILN          = 26, /**< Error Resilient(ER) HILN object           */
3146f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_PARA          = 27, /**< Error Resilient(ER) Parametric object     */
3147f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_28          = 28, /**< might become SSC                          */
3148f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_PS               = 29,   /**< PS, Parametric Stereo (includes SBR)      */
3149f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MPEGS            = 30, /**< MPEG Surround                             */
3150f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3151f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ESCAPE           = 31,   /**< Signal AOT uses more than 5 bits          */
3152f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3153f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MP3ONMP4_L1      = 32, /**< MPEG-Layer1 in mp4                        */
3154f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MP3ONMP4_L2      = 33, /**< MPEG-Layer2 in mp4                        */
3155f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MP3ONMP4_L3      = 34, /**< MPEG-Layer3 in mp4                        */
3156f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_35          = 35, /**< might become DST                          */
3157f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_36          = 36, /**< might become ALS                          */
3158f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_SLS          = 37, /**< AAC + SLS                                 */
3159f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_SLS              = 38, /**< SLS                                       */
3160f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_AAC_ELD       = 39, /**< AAC Enhanced Low Delay                    */
3161f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3162f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_USAC             = 42, /**< USAC                                      */
3163f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_SAOC             = 43, /**< SAOC                                      */
3164f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_LD_MPEGS         = 44, /**< Low Delay MPEG Surround                   */
3165f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3166f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD50           = 50,  /**< Interim AOT for Rsvd50                   */
3167f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi} AUDIO_OBJECT_TYPE;
3168f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3169ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
3170ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        const void *esds_data, size_t esds_size) {
3171ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    ESDS esds(esds_data, esds_size);
317281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
317381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    uint8_t objectTypeIndication;
317481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
317581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return ERROR_MALFORMED;
317681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
317781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
317881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (objectTypeIndication == 0xe1) {
317981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        // This isn't MPEG4 audio at all, it's QCELP 14k...
3180f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake        if (mLastTrack == NULL)
3181f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake            return ERROR_MALFORMED;
3182f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
318381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
318481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return OK;
318581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
318681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
3187633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong    if (objectTypeIndication  == 0x6b) {
3188633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // The media subtype is MP3 audio
3189633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // Our software MP3 audio decoder may not be able to handle
3190633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // packetized MP3 audio; for now, lets just return ERROR_UNSUPPORTED
319129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("MP3 track in MP4/3GPP file is not supported");
3192633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        return ERROR_UNSUPPORTED;
3193633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong    }
3194633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong
3195ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    const uint8_t *csd;
3196ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    size_t csd_size;
3197ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (esds.getCodecSpecificInfo(
3198ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                (const void **)&csd, &csd_size) != OK) {
3199ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
3200ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
3201ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3202b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    if (kUseHexDump) {
3203ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar        printf("ESD of size %zu\n", csd_size);
3204b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        hexdump(csd, csd_size);
3205b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    }
3206ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3207a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    if (csd_size == 0) {
3208a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // There's no further information, i.e. no codec specific data
3209a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // Let's assume that the information provided in the mpeg4 headers
3210a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // is accurate and hope for the best.
3211a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
3212a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        return OK;
3213a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    }
3214a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
3215ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (csd_size < 2) {
3216ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
3217ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
3218ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
321900307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent    static uint32_t kSamplingRate[] = {
322000307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
322100307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        16000, 12000, 11025, 8000, 7350
322200307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent    };
322300307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent
3224aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    ABitReader br(csd, csd_size);
3225aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    uint32_t objectType = br.getBits(5);
3226ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3227aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    if (objectType == 31) {  // AAC-ELD => additional 6 bits
3228aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        objectType = 32 + br.getBits(6);
3229ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
3230ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3231f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake    if (mLastTrack == NULL)
3232f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake        return ERROR_MALFORMED;
3233f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
3234db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent    //keep AOT type
3235db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent    mLastTrack->meta->setInt32(kKeyAACAOT, objectType);
3236db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent
3237aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    uint32_t freqIndex = br.getBits(4);
3238aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
3239ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t sampleRate = 0;
3240ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t numChannels = 0;
3241ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (freqIndex == 15) {
32428e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen        if (br.numBitsLeft() < 28) return ERROR_MALFORMED;
3243aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        sampleRate = br.getBits(24);
3244aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        numChannels = br.getBits(4);
3245ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    } else {
32468e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen        if (br.numBitsLeft() < 4) return ERROR_MALFORMED;
3247595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen        numChannels = br.getBits(4);
324800307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent
324900307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        if (freqIndex == 13 || freqIndex == 14) {
325000307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            return ERROR_MALFORMED;
3251ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
3252ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
325300307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        sampleRate = kSamplingRate[freqIndex];
325400307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent    }
3255595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen
3256f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    if (objectType == AOT_SBR || objectType == AOT_PS) {//SBR specific config per 14496-3 table 1.13
32578e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen        if (br.numBitsLeft() < 4) return ERROR_MALFORMED;
325800307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        uint32_t extFreqIndex = br.getBits(4);
3259b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe        int32_t extSampleRate __unused;
326000307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        if (extFreqIndex == 15) {
326100307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            if (csd_size < 8) {
3262595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen                return ERROR_MALFORMED;
3263595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen            }
32648e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen            if (br.numBitsLeft() < 24) return ERROR_MALFORMED;
326500307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            extSampleRate = br.getBits(24);
326600307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        } else {
326700307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            if (extFreqIndex == 13 || extFreqIndex == 14) {
326800307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent                return ERROR_MALFORMED;
326900307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            }
327000307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            extSampleRate = kSamplingRate[extFreqIndex];
3271595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen        }
327200307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        //TODO: save the extension sampling rate value in meta data =>
327300307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        //      mLastTrack->meta->setInt32(kKeyExtSampleRate, extSampleRate);
3274ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
3275ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3276f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    switch (numChannels) {
3277f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        // values defined in 14496-3_2009 amendment-4 Table 1.19 - Channel Configuration
3278f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 0:
3279f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 1:// FC
3280f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 2:// FL FR
3281f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 3:// FC, FL FR
3282f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 4:// FC, FL FR, RC
3283f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 5:// FC, FL FR, SL SR
3284f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 6:// FC, FL FR, SL SR, LFE
3285f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            //numChannels already contains the right value
3286f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            break;
3287f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 11:// FC, FL FR, SL SR, RC, LFE
3288f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            numChannels = 7;
3289f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            break;
3290f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 7: // FC, FCL FCR, FL FR, SL SR, LFE
3291f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 12:// FC, FL  FR,  SL SR, RL RR, LFE
3292f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 14:// FC, FL  FR,  SL SR, LFE, FHL FHR
3293f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            numChannels = 8;
3294f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            break;
3295f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        default:
3296f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            return ERROR_UNSUPPORTED;
3297f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    }
3298f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3299f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    {
3300f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        if (objectType == AOT_SBR || objectType == AOT_PS) {
33018e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen            if (br.numBitsLeft() < 5) return ERROR_MALFORMED;
3302f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            objectType = br.getBits(5);
3303f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3304f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            if (objectType == AOT_ESCAPE) {
33058e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                if (br.numBitsLeft() < 6) return ERROR_MALFORMED;
3306f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                objectType = 32 + br.getBits(6);
3307f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            }
3308f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        }
3309f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        if (objectType == AOT_AAC_LC || objectType == AOT_ER_AAC_LC ||
3310f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                objectType == AOT_ER_AAC_LD || objectType == AOT_ER_AAC_SCAL ||
3311f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                objectType == AOT_ER_BSAC) {
33128e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen            if (br.numBitsLeft() < 2) return ERROR_MALFORMED;
3313b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe            const int32_t frameLengthFlag __unused = br.getBits(1);
3314f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3315f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            const int32_t dependsOnCoreCoder = br.getBits(1);
3316f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3317f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            if (dependsOnCoreCoder ) {
33188e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                if (br.numBitsLeft() < 14) return ERROR_MALFORMED;
3319b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                const int32_t coreCoderDelay __unused = br.getBits(14);
3320f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            }
3321f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
332245452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            int32_t extensionFlag = -1;
332345452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            if (br.numBitsLeft() > 0) {
332445452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                extensionFlag = br.getBits(1);
332545452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            } else {
332645452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                switch (objectType) {
332745452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                // 14496-3 4.5.1.1 extensionFlag
332845452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_AAC_LC:
332945452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    extensionFlag = 0;
333045452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    break;
333145452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_ER_AAC_LC:
333245452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_ER_AAC_SCAL:
333345452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_ER_BSAC:
333445452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_ER_AAC_LD:
333545452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    extensionFlag = 1;
333645452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    break;
333745452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                default:
33388e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                    return ERROR_MALFORMED;
333945452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    break;
334045452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                }
334145452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                ALOGW("csd missing extension flag; assuming %d for object type %u.",
334245452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                        extensionFlag, objectType);
334345452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            }
3344f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
334545452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            if (numChannels == 0) {
3346f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                int32_t channelsEffectiveNum = 0;
3347f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                int32_t channelsNum = 0;
33488e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                if (br.numBitsLeft() < 32) {
33498e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                    return ERROR_MALFORMED;
33508e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                }
3351b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                const int32_t ElementInstanceTag __unused = br.getBits(4);
3352b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                const int32_t Profile __unused = br.getBits(2);
3353b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                const int32_t SamplingFrequencyIndex __unused = br.getBits(4);
3354f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumFrontChannelElements = br.getBits(4);
3355f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumSideChannelElements = br.getBits(4);
3356f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumBackChannelElements = br.getBits(4);
3357f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumLfeChannelElements = br.getBits(2);
3358b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                const int32_t NumAssocDataElements __unused = br.getBits(3);
3359b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                const int32_t NumValidCcElements __unused = br.getBits(4);
3360f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3361f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t MonoMixdownPresent = br.getBits(1);
33628e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen
3363f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                if (MonoMixdownPresent != 0) {
33648e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                    if (br.numBitsLeft() < 4) return ERROR_MALFORMED;
3365b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t MonoMixdownElementNumber __unused = br.getBits(4);
3366f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
3367f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
33688e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                if (br.numBitsLeft() < 1) return ERROR_MALFORMED;
3369f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t StereoMixdownPresent = br.getBits(1);
3370f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                if (StereoMixdownPresent != 0) {
33718e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                    if (br.numBitsLeft() < 4) return ERROR_MALFORMED;
3372b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t StereoMixdownElementNumber __unused = br.getBits(4);
3373f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
3374f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
33758e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                if (br.numBitsLeft() < 1) return ERROR_MALFORMED;
3376f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t MatrixMixdownIndexPresent = br.getBits(1);
3377f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                if (MatrixMixdownIndexPresent != 0) {
33788e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                    if (br.numBitsLeft() < 3) return ERROR_MALFORMED;
3379b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t MatrixMixdownIndex __unused = br.getBits(2);
3380b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t PseudoSurroundEnable __unused = br.getBits(1);
3381f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
3382f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3383f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                int i;
3384f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumFrontChannelElements; i++) {
33858e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                    if (br.numBitsLeft() < 5) return ERROR_MALFORMED;
3386f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t FrontElementIsCpe = br.getBits(1);
3387b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t FrontElementTagSelect __unused = br.getBits(4);
3388f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += FrontElementIsCpe ? 2 : 1;
3389f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
3390f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3391f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumSideChannelElements; i++) {
33928e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                    if (br.numBitsLeft() < 5) return ERROR_MALFORMED;
3393f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t SideElementIsCpe = br.getBits(1);
3394b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t SideElementTagSelect __unused = br.getBits(4);
3395f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += SideElementIsCpe ? 2 : 1;
3396f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
3397f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3398f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumBackChannelElements; i++) {
33998e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                    if (br.numBitsLeft() < 5) return ERROR_MALFORMED;
3400f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t BackElementIsCpe = br.getBits(1);
3401b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t BackElementTagSelect __unused = br.getBits(4);
3402f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += BackElementIsCpe ? 2 : 1;
3403f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
3404f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                channelsEffectiveNum = channelsNum;
3405f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3406f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumLfeChannelElements; i++) {
34078e0cc331a5b2e24016d8c5b8da11591cdd7c0fc0Marco Nelissen                    if (br.numBitsLeft() < 4) return ERROR_MALFORMED;
3408b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe                    const int32_t LfeElementTagSelect __unused = br.getBits(4);
3409f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += 1;
3410f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
3411f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                ALOGV("mpeg4 audio channelsNum = %d", channelsNum);
3412f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                ALOGV("mpeg4 audio channelsEffectiveNum = %d", channelsEffectiveNum);
3413f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                numChannels = channelsNum;
3414f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            }
3415f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        }
3416f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    }
3417f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
3418ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (numChannels == 0) {
3419ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_UNSUPPORTED;
3420ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
3421ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3422f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake    if (mLastTrack == NULL)
3423f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake        return ERROR_MALFORMED;
3424f35ff157134456d30f4cd32b463e32bbbf796cc9Joshua J. Drake
3425ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevSampleRate;
3426ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
3427ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3428ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevSampleRate != sampleRate) {
34293856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("mpeg4 audio sample rate different from previous setting. "
3430ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevSampleRate, sampleRate);
3431ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
3432ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3433ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
3434ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3435ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevChannelCount;
3436ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
3437ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3438ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevChannelCount != numChannels) {
34393856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("mpeg4 audio channel count different from previous setting. "
3440ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevChannelCount, numChannels);
3441ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
3442ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3443ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
3444ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
3445ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    return OK;
3446ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber}
3447ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
344820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
344920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
345020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::MPEG4Source(
3451942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen        const sp<MPEG4Extractor> &owner,
345220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        const sp<MetaData> &format,
3453693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &dataSource,
345448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        int32_t timeScale,
345505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const sp<SampleTable> &sampleTable,
345605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        Vector<SidxEntry> &sidx,
3457c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        const Trex *trex,
345805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t firstMoofOffset)
3459942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    : mOwner(owner),
3460942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen      mFormat(format),
346120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDataSource(dataSource),
346248c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber      mTimescale(timeScale),
346320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSampleTable(sampleTable),
346420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCurrentSampleIndex(0),
346505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentFragmentIndex(0),
346605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mSegments(sidx),
3467c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen      mTrex(trex),
346805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mFirstMoofOffset(firstMoofOffset),
346905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentMoofOffset(firstMoofOffset),
347005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentTime(0),
3471ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoAllocSize(0),
3472ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoSizes(NULL),
3473ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoOffsetsAllocSize(0),
3474ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoOffsets(NULL),
347520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mIsAVC(false),
34763b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar      mIsHEVC(false),
34776064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber      mNALLengthSize(0),
347820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mStarted(false),
347920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mGroup(NULL),
348020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mBuffer(NULL),
3481dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber      mWantsNALFragments(false),
34820024245e134467d120b40099da16c467dc365e76Andreas Huber      mSrcBuffer(NULL) {
3483ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3484c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    memset(&mTrackFragmentHeaderInfo, 0, sizeof(mTrackFragmentHeaderInfo));
3485c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
3486ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mFormat->findInt32(kKeyCryptoMode, &mCryptoMode);
348748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    mDefaultIVSize = 0;
3488ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mFormat->findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize);
3489ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t keytype;
3490ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    const void *key;
3491ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    size_t keysize;
3492ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mFormat->findData(kKeyCryptoKey, &keytype, &key, &keysize)) {
3493ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        CHECK(keysize <= 16);
3494ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memset(mCryptoKey, 0, 16);
3495ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memcpy(mCryptoKey, key, keysize);
3496ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3497ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
349820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
349920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mFormat->findCString(kKeyMIMEType, &mime);
3500dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(success);
350120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
350218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber    mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
35033b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    mIsHEVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC);
35046064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
35056064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    if (mIsAVC) {
35066064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        uint32_t type;
35076064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const void *data;
35086064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t size;
35096064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(format->findData(kKeyAVCC, &type, &data, &size));
35106064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
35116064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const uint8_t *ptr = (const uint8_t *)data;
35126064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
35136064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(size >= 7);
3514ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
35156064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
35166064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        // The number of bytes used to encode the length of a NAL unit.
35176064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        mNALLengthSize = 1 + (ptr[4] & 3);
35183b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    } else if (mIsHEVC) {
35193b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        uint32_t type;
35203b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        const void *data;
35213b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        size_t size;
35223b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        CHECK(format->findData(kKeyHVCC, &type, &data, &size));
35233b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
35243b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        const uint8_t *ptr = (const uint8_t *)data;
35253b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
3526a44ad9cefb0e2ff4091c8f58368c8b94779212aaWei Jia        CHECK(size >= 22);
35273b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
35283b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
35293b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        mNALLengthSize = 1 + (ptr[14 + 7] & 3);
35306064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
353105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
353205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    CHECK(format->findInt32(kKeyTrackID, &mTrackId));
353305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
353405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mFirstMoofOffset != 0) {
353505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t offset = mFirstMoofOffset;
353605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        parseChunk(&offset);
353705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
353820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
353920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
354020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::~MPEG4Source() {
354120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mStarted) {
354220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        stop();
354320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
3544ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    free(mCurrentSampleInfoSizes);
3545ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    free(mCurrentSampleInfoOffsets);
354620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
354720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
354820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::start(MetaData *params) {
35497b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
35507b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
3551dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(!mStarted);
355220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
355320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t val;
3554dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (params && params->findInt32(kKeyWantsNALFragments, &val)
355520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        && val != 0) {
3556dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = true;
355720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    } else {
3558dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = false;
355920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
356020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3561afd492436efc7f66b958da14659b52232efa5910Marco Nelissen    int32_t tmp;
3562afd492436efc7f66b958da14659b52232efa5910Marco Nelissen    CHECK(mFormat->findInt32(kKeyMaxInputSize, &tmp));
3563afd492436efc7f66b958da14659b52232efa5910Marco Nelissen    size_t max_size = tmp;
356420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3565afd492436efc7f66b958da14659b52232efa5910Marco Nelissen    // A somewhat arbitrary limit that should be sufficient for 8k video frames
3566afd492436efc7f66b958da14659b52232efa5910Marco Nelissen    // If you see the message below for a valid input stream: increase the limit
3567afd492436efc7f66b958da14659b52232efa5910Marco Nelissen    if (max_size > 64 * 1024 * 1024) {
3568afd492436efc7f66b958da14659b52232efa5910Marco Nelissen        ALOGE("bogus max input size: %zu", max_size);
3569afd492436efc7f66b958da14659b52232efa5910Marco Nelissen        return ERROR_MALFORMED;
3570afd492436efc7f66b958da14659b52232efa5910Marco Nelissen    }
3571afd492436efc7f66b958da14659b52232efa5910Marco Nelissen    mGroup = new MediaBufferGroup;
3572738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    mGroup->add_buffer(new MediaBuffer(max_size));
35730024245e134467d120b40099da16c467dc365e76Andreas Huber
35748da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    mSrcBuffer = new (std::nothrow) uint8_t[max_size];
35758da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    if (mSrcBuffer == NULL) {
35768da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        // file probably specified a bad max size
3577afd492436efc7f66b958da14659b52232efa5910Marco Nelissen        delete mGroup;
3578afd492436efc7f66b958da14659b52232efa5910Marco Nelissen        mGroup = NULL;
35798da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        return ERROR_MALFORMED;
35808da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    }
358120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
358220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = true;
358320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
358420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
358520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
358620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
358720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::stop() {
35887b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
35897b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
3590dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
359120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
359220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mBuffer != NULL) {
359320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->release();
359420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
359520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
359620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35970024245e134467d120b40099da16c467dc365e76Andreas Huber    delete[] mSrcBuffer;
35980024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = NULL;
35990024245e134467d120b40099da16c467dc365e76Andreas Huber
360020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    delete mGroup;
360120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = NULL;
360220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
360320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = false;
360420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mCurrentSampleIndex = 0;
360520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
360620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
360720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
360820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
360905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseChunk(off64_t *offset) {
361005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t hdr[2];
361105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
361205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_IO;
361305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
361405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t chunk_size = ntohl(hdr[0]);
361505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t chunk_type = ntohl(hdr[1]);
361605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t data_offset = *offset + 8;
361705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
361805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (chunk_size == 1) {
361905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
362005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_IO;
362105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
362205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        chunk_size = ntoh64(chunk_size);
362305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        data_offset += 8;
362405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
362505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (chunk_size < 16) {
362605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            // The smallest valid chunk is 16 bytes long in this case.
362705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
362805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
362905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (chunk_size < 8) {
363005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // The smallest valid chunk is 8 bytes long.
363105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
363205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
363305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
363405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    char chunk[5];
363505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    MakeFourCCString(chunk_type, chunk);
3636ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar    ALOGV("MPEG4Source chunk %s @ %#llx", chunk, (long long)*offset);
363705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
363805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t chunk_data_size = *offset + chunk_size - data_offset;
363905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
364005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    switch(chunk_type) {
364105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
364205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'r', 'a', 'f'):
364305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('m', 'o', 'o', 'f'): {
364405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t stop_offset = *offset + chunk_size;
364505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset = data_offset;
364605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            while (*offset < stop_offset) {
364705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err = parseChunk(offset);
364805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (err != OK) {
364905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return err;
365005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
365105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
365205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
36533f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                // *offset points to the box following this moof. Find the next moof from there.
36543f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen
36553f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                while (true) {
36563f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
36573f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                        return ERROR_END_OF_STREAM;
36583f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    }
36593f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    chunk_size = ntohl(hdr[0]);
36603f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    chunk_type = ntohl(hdr[1]);
36613f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
36623f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                        mNextMoofOffset = *offset;
36633f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                        break;
36643f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    }
36653f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    *offset += chunk_size;
36663f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                }
366705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
366805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
366905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
367005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
367105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'f', 'h', 'd'): {
367205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err;
367305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if ((err = parseTrackFragmentHeader(data_offset, chunk_data_size)) != OK) {
367405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return err;
367505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
367605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                *offset += chunk_size;
367705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                break;
367805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
367905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
368005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'r', 'u', 'n'): {
368105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err;
368205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (mLastParsedTrackId == mTrackId) {
368305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    if ((err = parseTrackFragmentRun(data_offset, chunk_data_size)) != OK) {
368405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        return err;
368505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    }
368605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
368705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
368805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                *offset += chunk_size;
368905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                break;
369005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
369105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3692ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'a', 'i', 'z'): {
3693ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            status_t err;
3694ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((err = parseSampleAuxiliaryInformationSizes(data_offset, chunk_data_size)) != OK) {
3695ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return err;
3696ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3697ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
3698ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
3699ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3700ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'a', 'i', 'o'): {
3701ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            status_t err;
3702ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((err = parseSampleAuxiliaryInformationOffsets(data_offset, chunk_data_size)) != OK) {
3703ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return err;
3704ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3705ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
3706ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
3707ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3708ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3709ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('m', 'd', 'a', 't'): {
3710ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // parse DRM info if present
3711ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("MPEG4Source::parseChunk mdat");
3712ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // if saiz/saoi was previously observed, do something with the sampleinfos
3713ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
3714ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
3715ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3716ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
371705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        default: {
371805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset += chunk_size;
371905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
372005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
372105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
372205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
372305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
372405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
372584333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG4Source::parseSampleAuxiliaryInformationSizes(
372684333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        off64_t offset, off64_t /* size */) {
3727ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("parseSampleAuxiliaryInformationSizes");
3728ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // 14496-12 8.7.12
3729ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t version;
3730ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(
3731ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset, &version, sizeof(version))
3732ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            < (ssize_t)sizeof(version)) {
3733ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3734ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3735ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3736ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (version != 0) {
3737ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_UNSUPPORTED;
3738ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3739ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
3740ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3741ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t flags;
3742ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt24(offset, &flags)) {
3743ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3744ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3745ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 3;
3746ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3747ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (flags & 1) {
3748ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        uint32_t tmp;
3749ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
3750ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_MALFORMED;
3751ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3752ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentAuxInfoType = tmp;
3753ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        offset += 4;
3754ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
3755ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_MALFORMED;
3756ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3757ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentAuxInfoTypeParameter = tmp;
3758ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        offset += 4;
3759ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3760ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3761ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t defsize;
3762ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(offset, &defsize, 1) != 1) {
3763ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_MALFORMED;
3764ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3765ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mCurrentDefaultSampleInfoSize = defsize;
3766ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
3767ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3768ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t smplcnt;
3769ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &smplcnt)) {
3770ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_MALFORMED;
3771ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
377248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    mCurrentSampleInfoCount = smplcnt;
3773ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 4;
3774ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
377548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (mCurrentDefaultSampleInfoSize != 0) {
377648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        ALOGV("@@@@ using default sample info size of %d", mCurrentDefaultSampleInfoSize);
377748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return OK;
377848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
3779ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (smplcnt > mCurrentSampleInfoAllocSize) {
3780ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoSizes = (uint8_t*) realloc(mCurrentSampleInfoSizes, smplcnt);
3781ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoAllocSize = smplcnt;
3782ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3783ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3784ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mDataSource->readAt(offset, mCurrentSampleInfoSizes, smplcnt);
3785ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    return OK;
3786ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen}
3787ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
378884333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(
378984333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        off64_t offset, off64_t /* size */) {
3790ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("parseSampleAuxiliaryInformationOffsets");
3791ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // 14496-12 8.7.13
3792ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t version;
3793ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(offset, &version, sizeof(version)) != 1) {
3794ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3795ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3796ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
3797ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3798ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t flags;
3799ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt24(offset, &flags)) {
3800ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3801ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3802ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 3;
3803ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3804ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t entrycount;
3805ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &entrycount)) {
3806ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3807ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3808ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 4;
3809c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia    if (entrycount == 0) {
3810c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia        return OK;
3811c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia    }
3812c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia    if (entrycount > UINT32_MAX / 8) {
3813c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia        return ERROR_MALFORMED;
3814c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia    }
3815ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3816ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (entrycount > mCurrentSampleInfoOffsetsAllocSize) {
3817c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia        uint64_t *newPtr = (uint64_t *)realloc(mCurrentSampleInfoOffsets, entrycount * 8);
3818c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia        if (newPtr == NULL) {
3819c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia            return NO_MEMORY;
3820c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia        }
3821c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia        mCurrentSampleInfoOffsets = newPtr;
3822ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoOffsetsAllocSize = entrycount;
3823ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3824ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mCurrentSampleInfoOffsetCount = entrycount;
3825ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3826c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia    if (mCurrentSampleInfoOffsets == NULL) {
3827c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia        return OK;
3828c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia    }
3829c51ab7dd82bf4e24666fc72a55e03e2f530204d5Wei Jia
3830ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < entrycount; i++) {
3831ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (version == 0) {
3832ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t tmp;
3833ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (!mDataSource->getUInt32(offset, &tmp)) {
3834ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
3835ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3836ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mCurrentSampleInfoOffsets[i] = tmp;
3837ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset += 4;
3838ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        } else {
3839ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint64_t tmp;
3840ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (!mDataSource->getUInt64(offset, &tmp)) {
3841ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
3842ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3843ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mCurrentSampleInfoOffsets[i] = tmp;
3844ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset += 8;
3845ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3846ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3847ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3848ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // parse clear/encrypted data
3849ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3850ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    off64_t drmoffset = mCurrentSampleInfoOffsets[0]; // from moof
3851ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3852ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    drmoffset += mCurrentMoofOffset;
3853ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int ivlength;
3854ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    CHECK(mFormat->findInt32(kKeyCryptoDefaultIVSize, &ivlength));
385548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
3856529c595b083f8a4c3175e2350fba5547e6008e00Marco Nelissen    // only 0, 8 and 16 byte initialization vectors are supported
3857529c595b083f8a4c3175e2350fba5547e6008e00Marco Nelissen    if (ivlength != 0 && ivlength != 8 && ivlength != 16) {
3858529c595b083f8a4c3175e2350fba5547e6008e00Marco Nelissen        ALOGW("unsupported IV length: %d", ivlength);
3859529c595b083f8a4c3175e2350fba5547e6008e00Marco Nelissen        return ERROR_MALFORMED;
3860529c595b083f8a4c3175e2350fba5547e6008e00Marco Nelissen    }
386148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    // read CencSampleAuxiliaryDataFormats
3862ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mCurrentSampleInfoCount; i++) {
3863529c595b083f8a4c3175e2350fba5547e6008e00Marco Nelissen        if (i >= mCurrentSamples.size()) {
3864529c595b083f8a4c3175e2350fba5547e6008e00Marco Nelissen            ALOGW("too few samples");
3865529c595b083f8a4c3175e2350fba5547e6008e00Marco Nelissen            break;
3866529c595b083f8a4c3175e2350fba5547e6008e00Marco Nelissen        }
3867ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Sample *smpl = &mCurrentSamples.editItemAt(i);
3868ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3869ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memset(smpl->iv, 0, 16);
3870ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (mDataSource->readAt(drmoffset, smpl->iv, ivlength) != ivlength) {
3871ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_IO;
3872ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3873ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3874ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        drmoffset += ivlength;
3875ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
387648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        int32_t smplinfosize = mCurrentDefaultSampleInfoSize;
387748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        if (smplinfosize == 0) {
387848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smplinfosize = mCurrentSampleInfoSizes[i];
3879ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
388048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        if (smplinfosize > ivlength) {
388148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint16_t numsubsamples;
388248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (!mDataSource->getUInt16(drmoffset, &numsubsamples)) {
3883ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
3884ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3885ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            drmoffset += 2;
388648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            for (size_t j = 0; j < numsubsamples; j++) {
388748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                uint16_t numclear;
388848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                uint32_t numencrypted;
388948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                if (!mDataSource->getUInt16(drmoffset, &numclear)) {
389048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                    return ERROR_IO;
389148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                }
389248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                drmoffset += 2;
389348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                if (!mDataSource->getUInt32(drmoffset, &numencrypted)) {
389448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                    return ERROR_IO;
389548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                }
389648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                drmoffset += 4;
389748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->clearsizes.add(numclear);
389848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->encryptedsizes.add(numencrypted);
3899ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
390048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        } else {
390148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smpl->clearsizes.add(0);
390248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smpl->encryptedsizes.add(smpl->size);
3903ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3904ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3905ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3906ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3907ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    return OK;
3908ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen}
3909ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
391005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentHeader(off64_t offset, off64_t size) {
391105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
391205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 8) {
391305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
391405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
391505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
391605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
3917ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags
391805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
391905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
392005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
392105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & 0xff000000) {
392205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
392305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
392405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
392505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, (uint32_t*)&mLastParsedTrackId)) {
392605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
392705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
392805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
392905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mLastParsedTrackId != mTrackId) {
393005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // this is not the right track, skip it
393105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
393205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
393305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
393405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mFlags = flags;
393505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mTrackID = mLastParsedTrackId;
393605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 8;
393705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 8;
393805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
393905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("fragment header: %08x %08x", flags, mTrackFragmentHeaderInfo.mTrackID);
394005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
394105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent) {
394205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 8) {
394305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
394405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
394505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
394605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset, &mTrackFragmentHeaderInfo.mBaseDataOffset)) {
394705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
394805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
394905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 8;
395005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 8;
395105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
395205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
395305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent) {
395405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
395505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
395605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
395705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
395805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mSampleDescriptionIndex)) {
395905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
396005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
396105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
396205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
396305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
396405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
396505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
396605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
396705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
396805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
396905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
397005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleDuration)) {
397105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
397205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
397305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
397405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
397505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
397605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
397705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
397805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
397905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
398005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
398105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
398205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleSize)) {
398305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
398405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
398505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
398605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
398705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
398805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
398905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
399005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
399105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
399205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
399305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
399405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleFlags)) {
399505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
399605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
399705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
399805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
399905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
400005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
400105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!(flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent)) {
400205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mTrackFragmentHeaderInfo.mBaseDataOffset = mCurrentMoofOffset;
400305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
400405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
400505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mDataOffset = 0;
400605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
400705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
400805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
400905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentRun(off64_t offset, off64_t size) {
401005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
401105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Extractor::parseTrackFragmentRun");
401205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 8) {
401305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
401405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
401505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
401605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    enum {
401705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kDataOffsetPresent                  = 0x01,
401805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kFirstSampleFlagsPresent            = 0x04,
401905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleDurationPresent              = 0x100,
402005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleSizePresent                  = 0x200,
402105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleFlagsPresent                 = 0x400,
402205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleCompositionTimeOffsetPresent = 0x800,
402305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
402405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
402505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
402605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) {
402705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
402805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
402905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("fragment run flags: %08x", flags);
403005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
403105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & 0xff000000) {
403205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
403305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
403405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
403505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if ((flags & kFirstSampleFlagsPresent) && (flags & kSampleFlagsPresent)) {
403605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // These two shall not be used together.
403705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
403805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
403905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
404005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t sampleCount;
404105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, &sampleCount)) {
404205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
404305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
404405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 8;
404505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 8;
404605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
404705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t dataOffset = mTrackFragmentHeaderInfo.mDataOffset;
404805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
404905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t firstSampleFlags = 0;
405005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
405105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kDataOffsetPresent) {
405205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
405305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
405405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
405505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
405605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int32_t dataOffsetDelta;
405705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, (uint32_t*)&dataOffsetDelta)) {
405805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
405905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
406005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
406105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        dataOffset = mTrackFragmentHeaderInfo.mBaseDataOffset + dataOffsetDelta;
406205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
406305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
406405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
406505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
406605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
406705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kFirstSampleFlagsPresent) {
406805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
406905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
407005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
407105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
407205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &firstSampleFlags)) {
407305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
407405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
407505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
407605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
407705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
407805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
407905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t sampleDuration = 0, sampleSize = 0, sampleFlags = 0,
408005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen             sampleCtsOffset = 0;
408105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
408205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size_t bytesPerSample = 0;
408305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleDurationPresent) {
408405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
408505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
408605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
408705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration;
4088c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    } else if (mTrex) {
4089c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        sampleDuration = mTrex->default_sample_duration;
409005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
409105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
409205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleSizePresent) {
409305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
409405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
409505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
409605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
409705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
409805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
409905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
410005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
410105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleFlagsPresent) {
410205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
410305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
410405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
410505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
410605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
410705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
410805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
410905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
411005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleCompositionTimeOffsetPresent) {
411105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
411205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
411305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleCtsOffset = 0;
411405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
411505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
4116ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar    if (size < (off64_t)(sampleCount * bytesPerSample)) {
411705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
411805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
411905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
412005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Sample tmp;
412105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    for (uint32_t i = 0; i < sampleCount; ++i) {
412205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleDurationPresent) {
412305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleDuration)) {
412405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
412505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
412605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
412705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
412805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
412905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleSizePresent) {
413005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleSize)) {
413105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
413205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
413305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
413405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
413505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
413605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleFlagsPresent) {
413705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleFlags)) {
413805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
413905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
414005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
414105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
414205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
414305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleCompositionTimeOffsetPresent) {
414405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleCtsOffset)) {
414505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
414605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
414705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
414805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
414905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
4150a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("adding sample %d at offset 0x%08" PRIx64 ", size %u, duration %u, "
4151ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen              " flags 0x%08x", i + 1,
415205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dataOffset, sampleSize, sampleDuration,
415305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                (flags & kFirstSampleFlagsPresent) && i == 0
415405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ? firstSampleFlags : sampleFlags);
415505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.offset = dataOffset;
415605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.size = sampleSize;
415705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.duration = sampleDuration;
4158c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        tmp.compositionOffset = sampleCtsOffset;
415905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentSamples.add(tmp);
416005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
416105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        dataOffset += sampleSize;
416205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
416305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
416405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mDataOffset = dataOffset;
416505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
416605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
416705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
416805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
416920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> MPEG4Source::getFormat() {
41707b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
41717b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
417220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return mFormat;
417320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
417420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
41756064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const {
41766064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    switch (mNALLengthSize) {
41776064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 1:
41786064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return *data;
41796064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 2:
41806064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U16_AT(data);
41816064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 3:
41826064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return ((size_t)data[0] << 16) | U16_AT(&data[1]);
41836064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 4:
41846064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U32_AT(data);
41856064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
41866064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
41876064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // This cannot happen, mNALLengthSize springs to life by adding 1 to
41886064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // a 2-bit integer.
41896064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    CHECK(!"Should not be here.");
41906064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
41916064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    return 0;
41926064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber}
41936064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
419420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::read(
419520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
41967b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
41977b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
4198dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
419920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
420005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mFirstMoofOffset > 0) {
420105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return fragmentedRead(out, options);
420205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
420305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
420420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *out = NULL;
420520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4206abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    int64_t targetSampleTimeUs = -1;
4207abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
420820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t seekTimeUs;
4209abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
4210abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
4211abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t findFlags = 0;
4212abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        switch (mode) {
4213abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_PREVIOUS_SYNC:
4214abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagBefore;
4215abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
4216abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_NEXT_SYNC:
4217abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagAfter;
4218abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
4219abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST_SYNC:
4220abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST:
4221abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagClosest;
4222abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
4223abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            default:
4224abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                CHECK(!"Should not be here.");
4225abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
4226abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
4227abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
422820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        uint32_t sampleIndex;
4229abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        status_t err = mSampleTable->findSampleAtTime(
4230599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar                seekTimeUs, 1000000, mTimescale,
4231abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                &sampleIndex, findFlags);
4232abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
4233abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
4234abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // We found the closest sample already, now we want the sync
4235abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // sample preceding it (or the sample itself of course), even
4236abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // if the subsequent sync sample is closer.
4237abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            findFlags = SampleTable::kFlagBefore;
4238abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
4239abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
4240abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleIndex;
4241abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (err == OK) {
4242abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            err = mSampleTable->findSyncSampleNear(
4243abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    sampleIndex, &syncSampleIndex, findFlags);
4244abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
424520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4246788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        uint32_t sampleTime;
4247788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        if (err == OK) {
4248788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber            err = mSampleTable->getMetaDataForSample(
4249788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber                    sampleIndex, NULL, NULL, &sampleTime);
4250788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        }
4251788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber
425220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (err != OK) {
42535295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            if (err == ERROR_OUT_OF_RANGE) {
42545295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // An attempt to seek past the end of the stream would
42555295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // normally cause this ERROR_OUT_OF_RANGE error. Propagating
42565295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // this all the way to the MediaPlayer would cause abnormal
42575295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // termination. Legacy behaviour appears to be to behave as if
42585295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // we had seeked to the end of stream, ending normally.
42595295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                err = ERROR_END_OF_STREAM;
42605295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            }
426105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("end of stream");
426220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return err;
426320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
426420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4265abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
4266abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
4267abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
4268abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
4269abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#if 0
4270abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleTime;
4271abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
4272abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    syncSampleIndex, NULL, NULL, &syncSampleTime));
4273abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
4274df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("seek to time %lld us => sample at time %lld us, "
4275abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             "sync sample at time %lld us",
4276abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             seekTimeUs,
4277abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             sampleTime * 1000000ll / mTimescale,
4278abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             syncSampleTime * 1000000ll / mTimescale);
4279abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#endif
4280abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
4281abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        mCurrentSampleIndex = syncSampleIndex;
428220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mBuffer != NULL) {
428320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
428420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
428520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
428620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
428720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // fall through
428820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
428920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4290c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset;
42910024245e134467d120b40099da16c467dc365e76Andreas Huber    size_t size;
4292170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih    uint32_t cts, stts;
42938bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    bool isSyncSample;
4294dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool newBuffer = false;
4295dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (mBuffer == NULL) {
4296dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        newBuffer = true;
429720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4298c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        status_t err =
4299c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber            mSampleTable->getMetaDataForSample(
4300170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                    mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample, &stts);
430120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4302dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
4303dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
4304dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
4305dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4306dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        err = mGroup->acquire_buffer(&mBuffer);
4307c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
4308dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
4309ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            CHECK(mBuffer == NULL);
4310dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
4311dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
4312c1a104aaad2d84a57bf5d87dd030d2bef56bf541Marco Nelissen        if (size > mBuffer->size()) {
4313c1a104aaad2d84a57bf5d87dd030d2bef56bf541Marco Nelissen            ALOGE("buffer too small: %zu > %zu", size, mBuffer->size());
4314c1a104aaad2d84a57bf5d87dd030d2bef56bf541Marco Nelissen            return ERROR_BUFFER_TOO_SMALL;
4315c1a104aaad2d84a57bf5d87dd030d2bef56bf541Marco Nelissen        }
43160024245e134467d120b40099da16c467dc365e76Andreas Huber    }
431720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43183b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    if ((!mIsAVC && !mIsHEVC) || mWantsNALFragments) {
4319dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (newBuffer) {
4320dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ssize_t num_bytes_read =
432134769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
4322dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4323dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            if (num_bytes_read < (ssize_t)size) {
4324dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer->release();
4325dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer = NULL;
4326dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4327dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                return ERROR_IO;
4328dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            }
4329dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
43307b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber            CHECK(mBuffer != NULL);
4331dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->set_range(0, size);
4332dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->meta_data()->clear();
433348c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mBuffer->meta_data()->setInt64(
43344678a6dc5f09008481524949a9667af5a6190374Andreas Huber                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
4335170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih            mBuffer->meta_data()->setInt64(
4336170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                    kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
4337abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
4338abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            if (targetSampleTimeUs >= 0) {
4339abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                mBuffer->meta_data()->setInt64(
4340abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                        kKeyTargetTime, targetSampleTimeUs);
4341abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            }
4342abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
43438bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            if (isSyncSample) {
43448bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
43458bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            }
43468bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
4347dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ++mCurrentSampleIndex;
4348dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
4349dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
43503b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        if (!mIsAVC && !mIsHEVC) {
4351dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            *out = mBuffer;
4352dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
4353dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4354dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return OK;
4355dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
4356dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4357dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Each NAL unit is split up into its constituent fragments and
4358dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // each one of them returned in its own buffer.
4359dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
43606064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(mBuffer->range_length() >= mNALLengthSize);
4361dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4362dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        const uint8_t *src =
4363dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
4364dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
43656064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t nal_size = parseNALSize(src);
43665d101298d8b0a78a1dc5bd26dbdada411f4ecd4dMarco Nelissen        if (mNALLengthSize > SIZE_MAX - nal_size) {
43675d101298d8b0a78a1dc5bd26dbdada411f4ecd4dMarco Nelissen            ALOGE("b/24441553, b/24445122");
43685d101298d8b0a78a1dc5bd26dbdada411f4ecd4dMarco Nelissen        }
43695d101298d8b0a78a1dc5bd26dbdada411f4ecd4dMarco Nelissen        if (mBuffer->range_length() - mNALLengthSize < nal_size) {
437029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("incomplete NAL unit.");
4371e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
4372e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer->release();
4373e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer = NULL;
4374e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
4375e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            return ERROR_MALFORMED;
4376e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        }
4377dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4378dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        MediaBuffer *clone = mBuffer->clone();
43797b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(clone != NULL);
43806064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
4381dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
43827b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(mBuffer != NULL);
4383dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mBuffer->set_range(
43846064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_offset() + mNALLengthSize + nal_size,
43856064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_length() - mNALLengthSize - nal_size);
4386dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4387dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (mBuffer->range_length() == 0) {
4388dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->release();
4389dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
4390dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
4391dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4392dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        *out = clone;
4393dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4394dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        return OK;
4395dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    } else {
4396dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Whole NAL units are returned but each fragment is prefixed by
4397dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // the start code (0x00 00 00 01).
4398dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        ssize_t num_bytes_read = 0;
4399dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        int32_t drm = 0;
4400dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
4401dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (usesDRM) {
4402dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            num_bytes_read =
4403dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
4404dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
4405dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
4406dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
440720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
440820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (num_bytes_read < (ssize_t)size) {
440920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
441020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
441120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4412dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return ERROR_IO;
441320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
441420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4415dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (usesDRM) {
4416dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK(mBuffer != NULL);
4417dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            mBuffer->set_range(0, size);
44186064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
4419dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
4420dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            uint8_t *dstData = (uint8_t *)mBuffer->data();
4421dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size_t srcOffset = 0;
4422dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size_t dstOffset = 0;
4423e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
4424dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            while (srcOffset < size) {
4425bfed843041b6aaec13ee19996748a7a1476db9c8Lajos Molnar                bool isMalFormed = !isInRange((size_t)0u, size, srcOffset, mNALLengthSize);
442634fe252c89e33572d01fea981b58d7b115e76164James Dong                size_t nalLength = 0;
442734fe252c89e33572d01fea981b58d7b115e76164James Dong                if (!isMalFormed) {
442834fe252c89e33572d01fea981b58d7b115e76164James Dong                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
442934fe252c89e33572d01fea981b58d7b115e76164James Dong                    srcOffset += mNALLengthSize;
4430bfed843041b6aaec13ee19996748a7a1476db9c8Lajos Molnar                    isMalFormed = !isInRange((size_t)0u, size, srcOffset, nalLength);
443134fe252c89e33572d01fea981b58d7b115e76164James Dong                }
4432e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
443334fe252c89e33572d01fea981b58d7b115e76164James Dong                if (isMalFormed) {
443429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                    ALOGE("Video is malformed");
4435dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    mBuffer->release();
4436dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    mBuffer = NULL;
4437dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return ERROR_MALFORMED;
4438dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
4439dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
4440dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                if (nalLength == 0) {
4441dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    continue;
4442dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
4443dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
444487afa840a40af570278e93251cfc5e55a6a3d92eMarco Nelissen                if (dstOffset > SIZE_MAX - 4 ||
444587afa840a40af570278e93251cfc5e55a6a3d92eMarco Nelissen                        dstOffset + 4 > SIZE_MAX - nalLength ||
444687afa840a40af570278e93251cfc5e55a6a3d92eMarco Nelissen                        dstOffset + 4 + nalLength > mBuffer->size()) {
444787afa840a40af570278e93251cfc5e55a6a3d92eMarco Nelissen                    ALOGE("b/27208621 : %zu %zu", dstOffset, mBuffer->size());
444887afa840a40af570278e93251cfc5e55a6a3d92eMarco Nelissen                    android_errorWriteLog(0x534e4554, "27208621");
444987afa840a40af570278e93251cfc5e55a6a3d92eMarco Nelissen                    mBuffer->release();
445087afa840a40af570278e93251cfc5e55a6a3d92eMarco Nelissen                    mBuffer = NULL;
445187afa840a40af570278e93251cfc5e55a6a3d92eMarco Nelissen                    return ERROR_MALFORMED;
445287afa840a40af570278e93251cfc5e55a6a3d92eMarco Nelissen                }
4453dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
4454dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
4455dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
4456dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
4457dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 1;
4458dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
4459dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                srcOffset += nalLength;
4460dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstOffset += nalLength;
4461dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
4462dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK_EQ(srcOffset, size);
4463dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK(mBuffer != NULL);
4464dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            mBuffer->set_range(0, dstOffset);
4465dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
4466dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
446720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->meta_data()->clear();
446848c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        mBuffer->meta_data()->setInt64(
44694678a6dc5f09008481524949a9667af5a6190374Andreas Huber                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
4470170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih        mBuffer->meta_data()->setInt64(
4471170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
4472abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
4473abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (targetSampleTimeUs >= 0) {
4474abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            mBuffer->meta_data()->setInt64(
4475abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    kKeyTargetTime, targetSampleTimeUs);
4476abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
4477abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
44788bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        if (isSyncSample) {
44798bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
44808bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        }
44818bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
448220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        ++mCurrentSampleIndex;
448320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
448420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        *out = mBuffer;
448520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
448620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
448720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
448820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
448920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
449020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
449105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::fragmentedRead(
449205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MediaBuffer **out, const ReadOptions *options) {
449305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
449405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Source::fragmentedRead");
449505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
449605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    CHECK(mStarted);
449705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
449805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    *out = NULL;
449905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
450005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t targetSampleTimeUs = -1;
450105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
450205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t seekTimeUs;
450305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ReadOptions::SeekMode mode;
450405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
450505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
450605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int numSidxEntries = mSegments.size();
450705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (numSidxEntries != 0) {
450805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            int64_t totalTime = 0;
450905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t totalOffset = mFirstMoofOffset;
451005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            for (int i = 0; i < numSidxEntries; i++) {
451105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                const SidxEntry *se = &mSegments[i];
451205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (totalTime + se->mDurationUs > seekTimeUs) {
451305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    // The requested time is somewhere in this segment
45143f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    if ((mode == ReadOptions::SEEK_NEXT_SYNC && seekTimeUs > totalTime) ||
451505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        (mode == ReadOptions::SEEK_CLOSEST_SYNC &&
451605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        (seekTimeUs - totalTime) > (totalTime + se->mDurationUs - seekTimeUs))) {
451705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        // requested next sync, or closest sync and it was closer to the end of
451805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        // this segment
451905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        totalTime += se->mDurationUs;
452005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        totalOffset += se->mSize;
452105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    }
452205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    break;
452305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
452405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                totalTime += se->mDurationUs;
452505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                totalOffset += se->mSize;
452605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
4527ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentMoofOffset = totalOffset;
4528ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSamples.clear();
4529ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSampleIndex = 0;
4530ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            parseChunk(&totalOffset);
4531ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentTime = totalTime * mTimescale / 1000000ll;
4532ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen        } else {
4533ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            // without sidx boxes, we can only seek to 0
4534ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentMoofOffset = mFirstMoofOffset;
4535ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSamples.clear();
4536ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSampleIndex = 0;
4537ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            off64_t tmp = mCurrentMoofOffset;
4538ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            parseChunk(&tmp);
4539ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentTime = 0;
454005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
454105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
454205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer != NULL) {
454305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
454405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
454505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
454605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
454705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // fall through
454805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
454905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
455005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t offset = 0;
4551442cc6dc48f8188e097617f7f804c314a9dacd0eAndreas Huber    size_t size = 0;
455205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t cts = 0;
455305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    bool isSyncSample = false;
455405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    bool newBuffer = false;
455505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mBuffer == NULL) {
455605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        newBuffer = true;
455705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
455805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mCurrentSampleIndex >= mCurrentSamples.size()) {
45593f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            // move to next fragment if there is one
45603f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            if (mNextMoofOffset <= mCurrentMoofOffset) {
45613f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                return ERROR_END_OF_STREAM;
45623f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            }
4563ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            off64_t nextMoof = mNextMoofOffset;
456405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentMoofOffset = nextMoof;
456505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentSamples.clear();
456605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentSampleIndex = 0;
456705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            parseChunk(&nextMoof);
4568ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            if (mCurrentSampleIndex >= mCurrentSamples.size()) {
4569ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen                return ERROR_END_OF_STREAM;
4570ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            }
457105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
457205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
457305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
457405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset = smpl->offset;
457505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size = smpl->size;
4576c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        cts = mCurrentTime + smpl->compositionOffset;
457705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentTime += smpl->duration;
457805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        isSyncSample = (mCurrentSampleIndex == 0); // XXX
457905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
458005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        status_t err = mGroup->acquire_buffer(&mBuffer);
458105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
458205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (err != OK) {
458305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer == NULL);
458405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("acquire_buffer returned %d", err);
458505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return err;
458605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
4587c1a104aaad2d84a57bf5d87dd030d2bef56bf541Marco Nelissen        if (size > mBuffer->size()) {
4588c1a104aaad2d84a57bf5d87dd030d2bef56bf541Marco Nelissen            ALOGE("buffer too small: %zu > %zu", size, mBuffer->size());
4589c1a104aaad2d84a57bf5d87dd030d2bef56bf541Marco Nelissen            return ERROR_BUFFER_TOO_SMALL;
4590c1a104aaad2d84a57bf5d87dd030d2bef56bf541Marco Nelissen        }
459105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
459205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
459348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
459448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    const sp<MetaData> bufmeta = mBuffer->meta_data();
459548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    bufmeta->clear();
459648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (smpl->encryptedsizes.size()) {
459748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // store clear/encrypted lengths in metadata
459848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyPlainSizes, 0,
459948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->clearsizes.array(), smpl->clearsizes.size() * 4);
460048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyEncryptedSizes, 0,
460148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
460248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
460348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
460448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setInt32(kKeyCryptoMode, mCryptoMode);
460548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16);
460648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
460748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
46083b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    if ((!mIsAVC && !mIsHEVC)|| mWantsNALFragments) {
460905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (newBuffer) {
4610da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            if (!isInRange((size_t)0u, mBuffer->size(), size)) {
4611da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                mBuffer->release();
4612da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                mBuffer = NULL;
4613da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih
4614da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                ALOGE("fragmentedRead ERROR_MALFORMED size %zu", size);
4615da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                return ERROR_MALFORMED;
4616da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            }
4617da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih
461805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ssize_t num_bytes_read =
461905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
462005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
462105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (num_bytes_read < (ssize_t)size) {
462205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->release();
462305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer = NULL;
462405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
4625da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                ALOGE("i/o error");
462605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_IO;
462705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
462805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
462905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
463005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, size);
463105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt64(
463205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
4633170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih            mBuffer->meta_data()->setInt64(
4634170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                    kKeyDuration, ((int64_t)smpl->duration * 1000000) / mTimescale);
463505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
463605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (targetSampleTimeUs >= 0) {
463705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->meta_data()->setInt64(
463805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        kKeyTargetTime, targetSampleTimeUs);
463905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
464005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
464105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (isSyncSample) {
464205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
464305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
464405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
464505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ++mCurrentSampleIndex;
464605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
464705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
46483b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        if (!mIsAVC && !mIsHEVC) {
464905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *out = mBuffer;
465005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
465105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
465205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return OK;
465305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
465405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
465505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // Each NAL unit is split up into its constituent fragments and
465605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // each one of them returned in its own buffer.
465705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
465805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(mBuffer->range_length() >= mNALLengthSize);
465905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
466005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const uint8_t *src =
466105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
466205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
466305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size_t nal_size = parseNALSize(src);
46645d101298d8b0a78a1dc5bd26dbdada411f4ecd4dMarco Nelissen        if (mNALLengthSize > SIZE_MAX - nal_size) {
46655d101298d8b0a78a1dc5bd26dbdada411f4ecd4dMarco Nelissen            ALOGE("b/24441553, b/24445122");
46665d101298d8b0a78a1dc5bd26dbdada411f4ecd4dMarco Nelissen        }
46675d101298d8b0a78a1dc5bd26dbdada411f4ecd4dMarco Nelissen
46685d101298d8b0a78a1dc5bd26dbdada411f4ecd4dMarco Nelissen        if (mBuffer->range_length() - mNALLengthSize < nal_size) {
466905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGE("incomplete NAL unit.");
467005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
467105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
467205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
467305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
467405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
467505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
467605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
467705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MediaBuffer *clone = mBuffer->clone();
467805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(clone != NULL);
467905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
468005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
468105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(mBuffer != NULL);
468205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer->set_range(
468305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->range_offset() + mNALLengthSize + nal_size,
468405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->range_length() - mNALLengthSize - nal_size);
468505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
468605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer->range_length() == 0) {
468705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
468805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
468905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
469005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
469105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        *out = clone;
469205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
469305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
469405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
469505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV("whole NAL");
469605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // Whole NAL units are returned but each fragment is prefixed by
469705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // the start code (0x00 00 00 01).
469805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ssize_t num_bytes_read = 0;
469905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int32_t drm = 0;
470005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
4701da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih        void *data = NULL;
4702da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih        bool isMalFormed = false;
470305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (usesDRM) {
4704da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            if (mBuffer == NULL || !isInRange((size_t)0u, mBuffer->size(), size)) {
4705da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                isMalFormed = true;
4706da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            } else {
4707da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                data = mBuffer->data();
4708da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            }
470905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else {
4710da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            int32_t max_size;
4711da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            if (mFormat == NULL
4712da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                    || !mFormat->findInt32(kKeyMaxInputSize, &max_size)
4713da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                    || !isInRange((size_t)0u, (size_t)max_size, size)) {
4714da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                isMalFormed = true;
4715da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            } else {
4716da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                data = mSrcBuffer;
4717da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            }
471805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
471905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
4720da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih        if (isMalFormed || data == NULL) {
4721da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            ALOGE("isMalFormed size %zu", size);
4722da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            if (mBuffer != NULL) {
4723da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                mBuffer->release();
4724da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                mBuffer = NULL;
4725da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            }
4726da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            return ERROR_MALFORMED;
4727da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih        }
4728da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih        num_bytes_read = mDataSource->readAt(offset, data, size);
4729da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih
473005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (num_bytes_read < (ssize_t)size) {
473105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
473205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
473305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
4734da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih            ALOGE("i/o error");
473505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_IO;
473605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
473705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
473805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (usesDRM) {
473905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
474005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, size);
474105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
474205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else {
474305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            uint8_t *dstData = (uint8_t *)mBuffer->data();
474405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            size_t srcOffset = 0;
474505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            size_t dstOffset = 0;
474605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
474705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            while (srcOffset < size) {
4748da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                isMalFormed = !isInRange((size_t)0u, size, srcOffset, mNALLengthSize);
474905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                size_t nalLength = 0;
475005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (!isMalFormed) {
475105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
475205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    srcOffset += mNALLengthSize;
4753da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                    isMalFormed = !isInRange((size_t)0u, size, srcOffset, nalLength)
4754da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                            || !isInRange((size_t)0u, mBuffer->size(), dstOffset, (size_t)4u)
4755da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                            || !isInRange((size_t)0u, mBuffer->size(), dstOffset + 4, nalLength);
475605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
475705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
475805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (isMalFormed) {
4759da93c7a3bd0da4acb2d920d4549ad9e302690af1Robert Shih                    ALOGE("Video is malformed; nalLength %zu", nalLength);
476005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    mBuffer->release();
476105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    mBuffer = NULL;
476205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return ERROR_MALFORMED;
476305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
476405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
476505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (nalLength == 0) {
476605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    continue;
476705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
476805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
47695403587a74aee2fb57076528c3927851531c8afbMarco Nelissen                if (dstOffset > SIZE_MAX - 4 ||
47705403587a74aee2fb57076528c3927851531c8afbMarco Nelissen                        dstOffset + 4 > SIZE_MAX - nalLength ||
47715403587a74aee2fb57076528c3927851531c8afbMarco Nelissen                        dstOffset + 4 + nalLength > mBuffer->size()) {
47725403587a74aee2fb57076528c3927851531c8afbMarco Nelissen                    ALOGE("b/26365349 : %zu %zu", dstOffset, mBuffer->size());
47735403587a74aee2fb57076528c3927851531c8afbMarco Nelissen                    android_errorWriteLog(0x534e4554, "26365349");
47745403587a74aee2fb57076528c3927851531c8afbMarco Nelissen                    mBuffer->release();
47755403587a74aee2fb57076528c3927851531c8afbMarco Nelissen                    mBuffer = NULL;
47765403587a74aee2fb57076528c3927851531c8afbMarco Nelissen                    return ERROR_MALFORMED;
47775403587a74aee2fb57076528c3927851531c8afbMarco Nelissen                }
477805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
477905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
478005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
478105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
478205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 1;
478305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
478405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                srcOffset += nalLength;
478505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstOffset += nalLength;
478605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
478705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK_EQ(srcOffset, size);
478805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
478905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, dstOffset);
479005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
479105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
479205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer->meta_data()->setInt64(
479305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
4794170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih        mBuffer->meta_data()->setInt64(
4795170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                kKeyDuration, ((int64_t)smpl->duration * 1000000) / mTimescale);
479605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
479705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (targetSampleTimeUs >= 0) {
479805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt64(
479905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    kKeyTargetTime, targetSampleTimeUs);
480005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
480105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
480205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (isSyncSample) {
480305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
480405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
480505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
480605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ++mCurrentSampleIndex;
480705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
480805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        *out = mBuffer;
480905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer = NULL;
481005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
481105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
481205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
481305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
481405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
4815bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas HuberMPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix(
4816bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        const char *mimePrefix) {
4817bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    for (Track *track = mFirstTrack; track != NULL; track = track->next) {
4818bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        const char *mime;
4819bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        if (track->meta != NULL
4820bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                && track->meta->findCString(kKeyMIMEType, &mime)
4821bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) {
4822bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber            return track;
4823bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        }
4824bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    }
4825bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber
4826bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    return NULL;
4827bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber}
4828bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber
48291b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool LegacySniffMPEG4(
4830693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
483120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[8];
483220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
483334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    ssize_t n = source->readAt(4, header, sizeof(header));
483420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (n < (ssize_t)sizeof(header)) {
483520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return false;
483620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
483720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
483820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
4839b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8)
4840b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8)
48410dba73763a04d39faf999dcc5ef12af3c99535a7Andreas Huber        || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
4842ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
4843983b449a27b5fa91eca82ede5204b4341899be62Andreas Huber        || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
484418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
48455a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        *confidence = 0.4;
484620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
484720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return true;
484820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
484920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
485020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return false;
485120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
485220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
48531b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool isCompatibleBrand(uint32_t fourcc) {
48541b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    static const uint32_t kCompatibleBrands[] = {
48551b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', 'm'),
48561b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', '2'),
48571b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('a', 'v', 'c', '1'),
48583b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        FOURCC('h', 'v', 'c', '1'),
48593b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        FOURCC('h', 'e', 'v', '1'),
48601b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('3', 'g', 'p', '4'),
48611b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '1'),
48621b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '2'),
48634cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong
48644cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        // Won't promise that the following file types can be played.
48654cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        // Just give these file types a chance.
48664cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        FOURCC('q', 't', ' ', ' '),  // Apple's QuickTime
48674cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        FOURCC('M', 'S', 'N', 'V'),  // Sony's PSP
486858fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber
486958fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber        FOURCC('3', 'g', '2', 'a'),  // 3GPP2
487058fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber        FOURCC('3', 'g', '2', 'b'),
48711b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    };
48721b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
48731b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    for (size_t i = 0;
48741b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]);
48751b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         ++i) {
48761b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        if (kCompatibleBrands[i] == fourcc) {
48771b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            return true;
48781b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
48791b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
48801b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
48811b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
48821b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
48831b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
48841b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// Attempt to actually parse the 'ftyp' atom and determine if a suitable
48851b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// compatible brand is present.
4886a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// Also try to identify where this file's metadata ends
4887a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// (end of the 'moov' atom) and report it to the caller as part of
4888a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// the metadata.
48891b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool BetterSniffMPEG4(
4890a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
4891a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        sp<AMessage> *meta) {
4892a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    // We scan up to 128 bytes to identify this file as an MP4.
4893a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    static const off64_t kMaxScanOffset = 128ll;
48941b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4895a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    off64_t offset = 0ll;
4896a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    bool foundGoodFileType = false;
4897a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    off64_t moovAtomEndOffset = -1ll;
4898a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    bool done = false;
48991b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4900a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    while (!done && offset < kMaxScanOffset) {
4901a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint32_t hdr[2];
4902a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        if (source->readAt(offset, hdr, 8) < 8) {
4903a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            return false;
4904a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        }
4905a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4906a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint64_t chunkSize = ntohl(hdr[0]);
4907a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint32_t chunkType = ntohl(hdr[1]);
4908a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        off64_t chunkDataOffset = offset + 8;
4909a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4910a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        if (chunkSize == 1) {
4911a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            if (source->readAt(offset + 8, &chunkSize, 8) < 8) {
49121b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                return false;
49131b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
49141b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4915a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            chunkSize = ntoh64(chunkSize);
4916a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            chunkDataOffset += 8;
4917a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4918a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            if (chunkSize < 16) {
4919a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                // The smallest valid chunk is 16 bytes long in this case.
4920a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                return false;
4921a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            }
4922452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen
4923a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        } else if (chunkSize < 8) {
4924a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            // The smallest valid chunk is 8 bytes long.
4925a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            return false;
4926a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        }
4927a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4928452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen        // (data_offset - offset) is either 8 or 16
4929452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen        off64_t chunkDataSize = chunkSize - (chunkDataOffset - offset);
4930452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen        if (chunkDataSize < 0) {
4931452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen            ALOGE("b/23540914");
4932452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen            return ERROR_MALFORMED;
4933452599f23a36207d436f7275ebc7e3ccac6ca76cMarco Nelissen        }
4934a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
493505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        char chunkstring[5];
493605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MakeFourCCString(chunkType, chunkstring);
4937ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar        ALOGV("saw chunk type %s, size %" PRIu64 " @ %lld", chunkstring, chunkSize, (long long)offset);
4938a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        switch (chunkType) {
4939a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            case FOURCC('f', 't', 'y', 'p'):
4940a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            {
4941a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                if (chunkDataSize < 8) {
4942a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    return false;
4943a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
4944a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4945a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4;
4946a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
4947a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (i == 1) {
4948a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        // Skip this index, it refers to the minorVersion,
4949a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        // not a brand.
4950a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        continue;
4951a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
4952a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4953a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    uint32_t brand;
4954a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (source->readAt(
4955a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                                chunkDataOffset + 4 * i, &brand, 4) < 4) {
4956a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        return false;
4957a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
4958a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4959a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    brand = ntohl(brand);
4960a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4961a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (isCompatibleBrand(brand)) {
4962a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        foundGoodFileType = true;
4963a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        break;
4964a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
4965a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
4966a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4967a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                if (!foundGoodFileType) {
4968a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    return false;
4969a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
4970a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
49711b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                break;
49721b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
4973a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4974a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            case FOURCC('m', 'o', 'o', 'v'):
4975a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            {
4976a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                moovAtomEndOffset = offset + chunkSize;
4977a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4978a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                done = true;
4979a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                break;
4980a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            }
4981a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4982a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            default:
4983a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                break;
49841b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
4985a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4986a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        offset += chunkSize;
49871b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
49881b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4989a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (!foundGoodFileType) {
49901b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return false;
49911b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
49921b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
49931b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
49945a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber    *confidence = 0.4f;
49951b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4996a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (moovAtomEndOffset >= 0) {
4997a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        *meta = new AMessage;
4998a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        (*meta)->setInt64("meta-data-size", moovAtomEndOffset);
4999a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
5000ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar        ALOGV("found metadata size: %lld", (long long)moovAtomEndOffset);
5001a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    }
5002a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
50031b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return true;
50041b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
50051b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
50061b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberbool SniffMPEG4(
50075a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
5008a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        sp<AMessage> *meta) {
5009a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (BetterSniffMPEG4(source, mimeType, confidence, meta)) {
50101b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
50111b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
50121b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
50131b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    if (LegacySniffMPEG4(source, mimeType, confidence)) {
50145ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Identified supported mpeg4 through LegacySniffMPEG4.");
50151b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
50161b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
50171b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
50181b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
50191b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
50201b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
502120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
5022