MPEG4Extractor.cpp revision c570778430a22b5488cae72982cf9fb8033dbda3
120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/*
220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright (C) 2009 The Android Open Source Project
320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License.
620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at
720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software
1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and
1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License.
1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */
1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen//#define LOG_NDEBUG 0
1820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#define LOG_TAG "MPEG4Extractor"
1989e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber
2020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <ctype.h>
21a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <inttypes.h>
2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <stdint.h>
2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <stdlib.h>
2420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <string.h>
2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <utils/Log.h>
27a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn
28a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include "include/MPEG4Extractor.h"
29a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include "include/SampleTable.h"
30a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include "include/ESDS.h"
31a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn
32aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke#include <media/stagefright/foundation/ABitReader.h>
33d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson#include <media/stagefright/foundation/ABuffer.h>
34ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#include <media/stagefright/foundation/ADebug.h>
35a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber#include <media/stagefright/foundation/AMessage.h>
36bfed843041b6aaec13ee19996748a7a1476db9c8Lajos Molnar#include <media/stagefright/foundation/AUtils.h>
3720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBufferGroup.h>
3918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/String8.h>
4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
44fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé#include <byteswap.h>
45328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé#include "include/ID3.h"
46fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
4720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Source : public MediaSource {
5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Caller retains ownership of both "dataSource" and "sampleTable".
52942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    MPEG4Source(const sp<MPEG4Extractor> &owner,
53942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen                const sp<MetaData> &format,
54693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber                const sp<DataSource> &dataSource,
5548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                int32_t timeScale,
5605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                const sp<SampleTable> &sampleTable,
5705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                Vector<SidxEntry> &sidx,
58c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                const Trex *trex,
5905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                off64_t firstMoofOffset);
6020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t start(MetaData *params = NULL);
6220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t stop();
6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual sp<MetaData> getFormat();
6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL);
6705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    virtual status_t fragmentedRead(MediaBuffer **buffer, const ReadOptions *options = NULL);
6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
69693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huberprotected:
70693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    virtual ~MPEG4Source();
71693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber
7220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
737b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex mLock;
747b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
75942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    // keep the MPEG4Extractor around, since we're referencing its data
76942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    sp<MPEG4Extractor> mOwner;
7720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mFormat;
78693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<DataSource> mDataSource;
7920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t mTimescale;
80693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<SampleTable> mSampleTable;
8120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t mCurrentSampleIndex;
8205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t mCurrentFragmentIndex;
8305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Vector<SidxEntry> &mSegments;
84c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    const Trex *mTrex;
8505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mFirstMoofOffset;
8605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mCurrentMoofOffset;
8705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mNextMoofOffset;
8805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t mCurrentTime;
8905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int32_t mLastParsedTrackId;
9005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int32_t mTrackId;
9120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
92ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int32_t mCryptoMode;    // passed in from extractor
93ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int32_t mDefaultIVSize; // passed in from extractor
94ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t mCryptoKey[16]; // passed in from extractor
95ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentAuxInfoType;
96ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentAuxInfoTypeParameter;
9748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    int32_t mCurrentDefaultSampleInfoSize;
98ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoCount;
99ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoAllocSize;
100ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t* mCurrentSampleInfoSizes;
101ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoOffsetCount;
102ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoOffsetsAllocSize;
103ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint64_t* mCurrentSampleInfoOffsets;
104ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mIsAVC;
1063b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    bool mIsHEVC;
1076064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    size_t mNALLengthSize;
1086064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
10920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mStarted;
11020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBufferGroup *mGroup;
11220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *mBuffer;
11420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
115dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool mWantsNALFragments;
11620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1170024245e134467d120b40099da16c467dc365e76Andreas Huber    uint8_t *mSrcBuffer;
1180024245e134467d120b40099da16c467dc365e76Andreas Huber
1196064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    size_t parseNALSize(const uint8_t *data) const;
12005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseChunk(off64_t *offset);
12105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseTrackFragmentHeader(off64_t offset, off64_t size);
12205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseTrackFragmentRun(off64_t offset, off64_t size);
123ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    status_t parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size);
124ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    status_t parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size);
12505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
12605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    struct TrackFragmentHeaderInfo {
12705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        enum Flags {
12805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kBaseDataOffsetPresent         = 0x01,
12905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kSampleDescriptionIndexPresent = 0x02,
13005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleDurationPresent  = 0x08,
13105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleSizePresent      = 0x10,
13205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleFlagsPresent     = 0x20,
13305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDurationIsEmpty               = 0x10000,
13405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        };
13505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
13605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mTrackID;
13705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mFlags;
13805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint64_t mBaseDataOffset;
13905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mSampleDescriptionIndex;
14005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleDuration;
14105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleSize;
14205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleFlags;
14305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
14405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint64_t mDataOffset;
14505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
14605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    TrackFragmentHeaderInfo mTrackFragmentHeaderInfo;
14705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
14805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    struct Sample {
14905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t offset;
15005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size_t size;
15105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t duration;
152c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        int32_t compositionOffset;
153ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        uint8_t iv[16];
154ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Vector<size_t> clearsizes;
155ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Vector<size_t> encryptedsizes;
15605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
15705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Vector<Sample> mCurrentSamples;
1586064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
15920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source(const MPEG4Source &);
16020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source &operator=(const MPEG4Source &);
16120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
16220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
16350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This custom data source wraps an existing one and satisfies requests
16450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// falling entirely within a cached range from the cache while forwarding
16550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// all remaining requests to the wrapped datasource.
16650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This is used to cache the full sampletable metadata for a single track,
16750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// possibly wrapping multiple times to cover all tracks, i.e.
16850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// Each MPEG4DataSource caches the sampletable metadata for a single track.
16950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstruct MPEG4DataSource : public DataSource {
17150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource(const sp<DataSource> &source);
17250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual status_t initCheck() const;
174c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
175c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    virtual status_t getSize(off64_t *size);
17650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual uint32_t flags();
17750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
178c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    status_t setCachedRange(off64_t offset, size_t size);
17950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprotected:
18150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual ~MPEG4DataSource();
18250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprivate:
18450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex mLock;
18550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    sp<DataSource> mSource;
187c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t mCachedOffset;
18850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    size_t mCachedSize;
18950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    uint8_t *mCache;
19050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    void clearCache();
19250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource(const MPEG4DataSource &);
19450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource &operator=(const MPEG4DataSource &);
19550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber};
19650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source)
19850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    : mSource(source),
19950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCachedOffset(0),
20050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCachedSize(0),
20150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCache(NULL) {
20250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
20350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
20450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::~MPEG4DataSource() {
20550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    clearCache();
20650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
20750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
20850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Hubervoid MPEG4DataSource::clearCache() {
20950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (mCache) {
21050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        free(mCache);
21150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        mCache = NULL;
21250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
21350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
21450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedOffset = 0;
21550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedSize = 0;
21650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
21750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
21850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstatus_t MPEG4DataSource::initCheck() const {
21950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->initCheck();
22050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
22150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
222c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongssize_t MPEG4DataSource::readAt(off64_t offset, void *data, size_t size) {
22350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex::Autolock autoLock(mLock);
22450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
225bfed843041b6aaec13ee19996748a7a1476db9c8Lajos Molnar    if (isInRange(mCachedOffset, mCachedSize, offset, size)) {
22650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        memcpy(data, &mCache[offset - mCachedOffset], size);
22750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return size;
22850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
22950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
23050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->readAt(offset, data, size);
23150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
23250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
233c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4DataSource::getSize(off64_t *size) {
23450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->getSize(size);
23550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
23650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
23750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberuint32_t MPEG4DataSource::flags() {
23850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->flags();
23950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
24050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
241c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4DataSource::setCachedRange(off64_t offset, size_t size) {
24250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex::Autolock autoLock(mLock);
24350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
24450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    clearCache();
24550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
24650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCache = (uint8_t *)malloc(size);
24750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
24850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (mCache == NULL) {
24950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return -ENOMEM;
25050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
25150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
25250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedOffset = offset;
25350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedSize = size;
25450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
25550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    ssize_t err = mSource->readAt(mCachedOffset, mCache, mCachedSize);
25650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
25750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (err < (ssize_t)size) {
25850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        clearCache();
25950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
26050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return ERROR_IO;
26150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
26250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
26350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return OK;
26450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
26550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
26650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber////////////////////////////////////////////////////////////////////////////////
26750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
26820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatic void hexdump(const void *_data, size_t size) {
26920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const uint8_t *data = (const uint8_t *)_data;
27020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t offset = 0;
27120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (offset < size) {
272377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        printf("0x%04zx  ", offset);
27320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        size_t n = size - offset;
27520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (n > 16) {
27620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            n = 16;
27720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < 16; ++i) {
28020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (i == 8) {
28120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(" ");
28220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
28320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (offset + i < size) {
28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%02x ", data[offset + i]);
28620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("   ");
28820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
29020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf(" ");
29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < n; ++i) {
29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (isprint(data[offset + i])) {
29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%c", data[offset + i]);
29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(".");
29820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
29920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf("\n");
30220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        offset += 16;
30420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
30520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
30620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huberstatic const char *FourCC2MIME(uint32_t fourcc) {
30820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch (fourcc) {
30920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
31018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AAC;
31120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
31318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_NB;
31420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
315371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
31618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_WB;
317371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
31820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
31918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_MPEG4;
32020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
322e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('h', '2', '6', '3'):
323e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('H', '2', '6', '3'):
32418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_H263;
32520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
32718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_AVC;
32820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3293b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'v', 'c', '1'):
3303b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'e', 'v', '1'):
3313b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            return MEDIA_MIMETYPE_VIDEO_HEVC;
33220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
333dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(!"should not be here.");
33420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
33520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
33620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
33720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissenstatic bool AdjustChannelsAndRate(uint32_t fourcc, uint32_t *channels, uint32_t *rate) {
33948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, FourCC2MIME(fourcc))) {
34048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // AMR NB audio is always mono, 8kHz
34148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *channels = 1;
34248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *rate = 8000;
34348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return true;
34448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, FourCC2MIME(fourcc))) {
34548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // AMR WB audio is always mono, 16kHz
34648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *channels = 1;
34748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *rate = 16000;
34848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return true;
34948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
35048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    return false;
35148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen}
35248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
353693d271e62a3726689ff68f4505ba49228eb94b2Andreas HuberMPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
354c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    : mMoofOffset(0),
35505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mDataSource(source),
356bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber      mInitCheck(NO_INIT),
3577be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber      mHasVideo(false),
358fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen      mHeaderTimescale(0),
35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mFirstTrack(NULL),
36072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber      mLastTrack(NULL),
361dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mFileMetaData(new MetaData),
362dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mFirstSINF(NULL),
363dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mIsDrm(false) {
36420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
36520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Extractor::~MPEG4Extractor() {
36720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
36820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
36920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        Track *next = track->next;
37020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete track;
37220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = next;
37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFirstTrack = mLastTrack = NULL;
375dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
376dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    SINF *sinf = mFirstSINF;
377dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (sinf) {
378dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        SINF *next = sinf->next;
3798da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        delete[] sinf->IPMPData;
380dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        delete sinf;
381dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf = next;
382dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
383dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    mFirstSINF = NULL;
384ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
385ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mPssh.size(); i++) {
386ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        delete [] mPssh[i].data;
387ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
38820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
38920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
39005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenuint32_t MPEG4Extractor::flags() const {
39105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return CAN_PAUSE |
39205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ((mMoofOffset == 0 || mSidxEntries.size() != 0) ?
39305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    (CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK) : 0);
39405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
39505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3967be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Hubersp<MetaData> MPEG4Extractor::getMetaData() {
3977be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    status_t err;
3987be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    if ((err = readMetaData()) != OK) {
39972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return new MetaData;
4007be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    }
4017be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
40272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return mFileMetaData;
4037be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber}
4047be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
405693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersize_t MPEG4Extractor::countTracks() {
40620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
40720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
408ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        ALOGV("MPEG4Extractor::countTracks: no tracks");
409693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return 0;
41020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
41120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
412693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    size_t n = 0;
41320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
41420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
415693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        ++n;
41620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
41720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
41820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
419a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("MPEG4Extractor::countTracks: %zu tracks", n);
420693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    return n;
42120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
42220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4237e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Hubersp<MetaData> MPEG4Extractor::getTrackMetaData(
4247e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        size_t index, uint32_t flags) {
42520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
42620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
42720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return NULL;
42820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
42920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
43120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
43220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
43320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
43420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
43520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
43720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
43820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
43920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
440371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
441371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
442371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
443371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
4447e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    if ((flags & kIncludeExtensiveMetaData)
4457e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            && !track->includes_expensive_metadata) {
4467e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        track->includes_expensive_metadata = true;
4477e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
4487e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        const char *mime;
4497e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        CHECK(track->meta->findCString(kKeyMIMEType, &mime));
4507e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        if (!strncasecmp("video/", mime, 6)) {
45105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (mMoofOffset > 0) {
45205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                int64_t duration;
45305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (track->meta->findInt64(kKeyDuration, &duration)) {
45405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    // nothing fancy, just pick a frame near 1/4th of the duration
45505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    track->meta->setInt64(
45605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            kKeyThumbnailTime, duration / 4);
45705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
45805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            } else {
45905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t sampleIndex;
46005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t sampleTime;
46105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK
46205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        && track->sampleTable->getMetaDataForSample(
46305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            sampleIndex, NULL /* offset */, NULL /* size */,
46405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            &sampleTime) == OK) {
46505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    track->meta->setInt64(
46605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            kKeyThumbnailTime,
46705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            ((int64_t)sampleTime * 1000000) / track->timescale);
46805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
4697e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            }
4707e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        }
4717e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    }
4727e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
47320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return track->meta;
47420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
47520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
47648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissenstatic void MakeFourCCString(uint32_t x, char *s) {
47748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[0] = x >> 24;
47848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[1] = (x >> 16) & 0xff;
47948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[2] = (x >> 8) & 0xff;
48048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[3] = x & 0xff;
48148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[4] = '\0';
48248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen}
48348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
48420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Extractor::readMetaData() {
485bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    if (mInitCheck != NO_INIT) {
486bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        return mInitCheck;
48720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
48820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
489c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = 0;
49020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
49105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    while (true) {
492a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen        off64_t orig_offset = offset;
49305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        err = parseChunk(&offset, 0);
494a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen
4954ff2a0dbb178c4ea652f30aa4f1d3deb9fdbc832Lajos Molnar        if (err != OK && err != UNKNOWN_ERROR) {
4964ff2a0dbb178c4ea652f30aa4f1d3deb9fdbc832Lajos Molnar            break;
4974ff2a0dbb178c4ea652f30aa4f1d3deb9fdbc832Lajos Molnar        } else if (offset <= orig_offset) {
498a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            // only continue parsing if the offset was advanced,
499a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            // otherwise we might end up in an infinite loop
500a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            ALOGE("did not advance: 0x%lld->0x%lld", orig_offset, offset);
501a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            err = ERROR_MALFORMED;
502a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            break;
503a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen        } else if (err == OK) {
50405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            continue;
50505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
5064ff2a0dbb178c4ea652f30aa4f1d3deb9fdbc832Lajos Molnar
50705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t hdr[2];
50805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mDataSource->readAt(offset, hdr, 8) < 8) {
50905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
51005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
51105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t chunk_type = ntohl(hdr[1]);
5123f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen        if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
51305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            // store the offset of the first segment
51405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mMoofOffset = offset;
5153f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen        } else if (chunk_type != FOURCC('m', 'd', 'a', 't')) {
5163f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            // keep parsing until we get to the data
5173f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            continue;
51805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
51905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        break;
52020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
5217be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
522bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    if (mInitCheck == OK) {
52372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        if (mHasVideo) {
524bc8b5faec8a0a9ad7c8d94945e7b000d63f0afe6Andreas Huber            mFileMetaData->setCString(
525bc8b5faec8a0a9ad7c8d94945e7b000d63f0afe6Andreas Huber                    kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG4);
52672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else {
52772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
52872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
529bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    } else {
530bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        mInitCheck = err;
53120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
53220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
533bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    CHECK_NE(err, (status_t)NO_INIT);
534ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
535ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // copy pssh data into file metadata
536ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int psshsize = 0;
537ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mPssh.size(); i++) {
538ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        psshsize += 20 + mPssh[i].datalen;
539ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
540ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (psshsize) {
541ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        char *buf = (char*)malloc(psshsize);
542ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        char *ptr = buf;
543ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        for (size_t i = 0; i < mPssh.size(); i++) {
544ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memcpy(ptr, mPssh[i].uuid, 20); // uuid + length
545ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memcpy(ptr + 20, mPssh[i].data, mPssh[i].datalen);
546ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ptr += (20 + mPssh[i].datalen);
547ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
548ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mFileMetaData->setData(kKeyPssh, 'pssh', buf, psshsize);
549ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        free(buf);
550ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
551bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    return mInitCheck;
55220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
55320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
554dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wangchar* MPEG4Extractor::getDrmTrackInfo(size_t trackID, int *len) {
555dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mFirstSINF == NULL) {
556dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return NULL;
557dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
558dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
559dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    SINF *sinf = mFirstSINF;
560dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (sinf && (trackID != sinf->trackID)) {
561dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf = sinf->next;
562dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
563dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
564dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (sinf == NULL) {
565dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return NULL;
566dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
567dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
568dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    *len = sinf->len;
569dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return sinf->IPMPData;
570dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
571dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
572dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang// Reads an encoded integer 7 bits at a time until it encounters the high bit clear.
57356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenstatic int32_t readSize(off64_t offset,
574dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        const sp<DataSource> DataSource, uint8_t *numOfBytes) {
575dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint32_t size = 0;
576dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t data;
577dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    bool moreData = true;
578dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    *numOfBytes = 0;
579dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
580dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (moreData) {
581dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (DataSource->readAt(offset, &data, 1) < 1) {
582dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return -1;
583dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
584dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        offset ++;
585dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        moreData = (data >= 128) ? true : false;
586dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        size = (size << 7) | (data & 0x7f); // Take last 7 bits
587dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        (*numOfBytes) ++;
588dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
589dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
590dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return size;
591dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
592dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
59384333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG4Extractor::parseDrmSINF(
59484333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        off64_t * /* offset */, off64_t data_offset) {
595dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t updateIdTag;
596dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
597dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
598dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
599dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset ++;
600dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
601dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (0x01/*OBJECT_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
602dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
603dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
604dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
605dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t numOfBytes;
606dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    int32_t size = readSize(data_offset, mDataSource, &numOfBytes);
607dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size < 0) {
608dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
609dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
610dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    int32_t classSize = size;
611dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset += numOfBytes;
612dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
613dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while(size >= 11 ) {
614dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t descriptorTag;
615dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, &descriptorTag, 1) < 1) {
616dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
617dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
618dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset ++;
619dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
620dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (0x11/*OBJECT_DESCRIPTOR_ID_TAG*/ != descriptorTag) {
621dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
622dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
623dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
624dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t buffer[8];
625dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        //ObjectDescriptorID and ObjectDescriptor url flag
626dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, buffer, 2) < 2) {
627dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
628dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
629dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset += 2;
630dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
631dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if ((buffer[1] >> 5) & 0x0001) { //url flag is set
632dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
633dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
634dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
635dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, buffer, 8) < 8) {
636dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
637dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
638dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset += 8;
639dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
640dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if ((0x0F/*ES_ID_REF_TAG*/ != buffer[1])
641dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                || ( 0x0A/*IPMP_DESCRIPTOR_POINTER_ID_TAG*/ != buffer[5])) {
642dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
643dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
644dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
645dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        SINF *sinf = new SINF;
646dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->trackID = U16_AT(&buffer[3]);
647dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->IPMPDescriptorID = buffer[7];
648dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->next = mFirstSINF;
649dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        mFirstSINF = sinf;
650dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
651dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        size -= (8 + 2 + 1);
652dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
653dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
654dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size != 0) {
655dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
656dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
657dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
658dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
659dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
660dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
661dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset ++;
662dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
663dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if(0x05/*IPMP_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
664dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
665dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
666dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
667dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    size = readSize(data_offset, mDataSource, &numOfBytes);
668dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size < 0) {
669dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
670dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
671dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    classSize = size;
672dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset += numOfBytes;
673dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
674dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (size > 0) {
675dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t tag;
676dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        int32_t dataLen;
677dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, &tag, 1) < 1) {
678dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
679dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
680dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset ++;
681dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
682dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (0x0B/*IPMP_DESCRIPTOR_ID_TAG*/ == tag) {
683dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            uint8_t id;
684dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            dataLen = readSize(data_offset, mDataSource, &numOfBytes);
685dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (dataLen < 0) {
686dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
687dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            } else if (dataLen < 4) {
688dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
689dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
690dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset += numOfBytes;
691dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
692dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (mDataSource->readAt(data_offset, &id, 1) < 1) {
693dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
694dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
695dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset ++;
696dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
697dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            SINF *sinf = mFirstSINF;
698dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            while (sinf && (sinf->IPMPDescriptorID != id)) {
699dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                sinf = sinf->next;
700dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
701dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (sinf == NULL) {
702dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
703dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
704dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            sinf->len = dataLen - 3;
7058da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            sinf->IPMPData = new (std::nothrow) char[sinf->len];
7068da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            if (sinf->IPMPData == NULL) {
7078da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen                return ERROR_MALFORMED;
7088da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            }
709f7df9ab3187a3c02bffe1fba10d3fb95197e4a07Ichitaro Kohara            data_offset += 2;
710dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
711f7df9ab3187a3c02bffe1fba10d3fb95197e4a07Ichitaro Kohara            if (mDataSource->readAt(data_offset, sinf->IPMPData, sinf->len) < sinf->len) {
712dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
713dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
714dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset += sinf->len;
715dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
716dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size -= (dataLen + numOfBytes + 1);
717dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
718dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
719dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
720dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size != 0) {
721dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
722dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
723dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
724dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return UNKNOWN_ERROR;  // Return a dummy error.
725dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
726dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
72772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstruct PathAdder {
72872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder(Vector<uint32_t> *path, uint32_t chunkType)
72972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        : mPath(path) {
73072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        mPath->push(chunkType);
73172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
73272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
73372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    ~PathAdder() {
73472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        mPath->pop();
73572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
73672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
73772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberprivate:
73872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    Vector<uint32_t> *mPath;
73972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
74072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder(const PathAdder &);
74172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder &operator=(const PathAdder &);
74272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber};
74372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
74472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic bool underMetaDataPath(const Vector<uint32_t> &path) {
74572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return path.size() >= 5
74672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[0] == FOURCC('m', 'o', 'o', 'v')
74772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[1] == FOURCC('u', 'd', 't', 'a')
74872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[2] == FOURCC('m', 'e', 't', 'a')
74972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[3] == FOURCC('i', 'l', 's', 't');
75072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
75172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
75272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber// Given a time in seconds since Jan 1 1904, produce a human-readable string.
75372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic void convertTimeToDate(int64_t time_1904, String8 *s) {
75472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    time_t time_1970 = time_1904 - (((66 * 365 + 17) * 24) * 3600);
75572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
75672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    char tmp[32];
75772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", gmtime(&time_1970));
75872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
75972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    s->setTo(tmp);
76072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
76172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
762c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
7635d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    ALOGV("entering parseChunk %lld/%d", *offset, depth);
76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t hdr[2];
76534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_IO;
76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
76820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint64_t chunk_size = ntohl(hdr[0]);
76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t chunk_type = ntohl(hdr[1]);
770c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t data_offset = *offset + 8;
77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (chunk_size == 1) {
77334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
77420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_IO;
77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        chunk_size = ntoh64(chunk_size);
77720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        data_offset += 8;
77871b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber
77971b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        if (chunk_size < 16) {
78071b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber            // The smallest valid chunk is 16 bytes long in this case.
78171b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber            return ERROR_MALFORMED;
78271b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        }
783a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen    } else if (chunk_size == 0) {
784a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen        if (depth == 0) {
785a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            // atom extends to end of file
786a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            off64_t sourceSize;
787a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            if (mDataSource->getSize(&sourceSize) == OK) {
788a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen                chunk_size = (sourceSize - *offset);
789a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            } else {
790a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen                // XXX could we just pick a "sufficiently large" value here?
791a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen                ALOGE("atom size is 0, and data source has no size");
792a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen                return ERROR_MALFORMED;
793a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            }
794a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen        } else {
795a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            // not allowed for non-toplevel atoms, skip it
796a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            *offset += 4;
797a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen            return OK;
798a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen        }
79971b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber    } else if (chunk_size < 8) {
80071b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        // The smallest valid chunk is 8 bytes long.
801a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGE("invalid chunk size: %" PRIu64, chunk_size);
80271b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        return ERROR_MALFORMED;
80320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
80420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
80520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    char chunk[5];
80620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MakeFourCCString(chunk_type, chunk);
80705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("chunk: %s @ %lld, %d", chunk, *offset, depth);
80820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
80920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#if 0
81020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static const char kWhitespace[] = "                                        ";
81120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
812a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    printf("%sfound chunk '%s' of size %" PRIu64 "\n", indent, chunk, chunk_size);
81320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
81420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    char buffer[256];
815ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    size_t n = chunk_size;
816ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    if (n > sizeof(buffer)) {
817ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        n = sizeof(buffer);
818ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    }
819ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    if (mDataSource->readAt(*offset, buffer, n)
820ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber            < (ssize_t)n) {
821ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        return ERROR_IO;
82220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
823ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
824ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    hexdump(buffer, n);
82520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#endif
82620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
82772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder autoAdder(&mPath, chunk_type);
82872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
829c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t chunk_data_size = *offset + chunk_size - data_offset;
83020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
83172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (chunk_type != FOURCC('c', 'p', 'r', 't')
832515e855eae78aa495da58356486aaa666cb57fd1James Dong            && chunk_type != FOURCC('c', 'o', 'v', 'r')
83372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            && mPath.size() == 5 && underMetaDataPath(mPath)) {
834c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t stop_offset = *offset + chunk_size;
83572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        *offset = data_offset;
83672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        while (*offset < stop_offset) {
83772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            status_t err = parseChunk(offset, depth + 1);
83872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (err != OK) {
83972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return err;
84072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
84172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
842bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
843bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (*offset != stop_offset) {
844bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
845bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
84672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
84772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return OK;
84872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
84972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
85020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch(chunk_type) {
85120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'v'):
85220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'k'):
85320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'i', 'a'):
85420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'i', 'n', 'f'):
85520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('d', 'i', 'n', 'f'):
85620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'b', 'l'):
85720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'v', 'e', 'x'):
85820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'f'):
85920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'f'):
86020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'f', 'r', 'a'):
86172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('u', 'd', 't', 'a'):
86272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('i', 'l', 's', 't'):
863ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'i', 'n', 'f'):
864ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'c', 'h', 'i'):
8650a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        case FOURCC('e', 'd', 't', 's'):
86620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
86750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
868a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                ALOGV("sampleTable chunk is %" PRIu64 " bytes long.", chunk_size);
86950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
870b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                if (mDataSource->flags()
871b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                        & (DataSource::kWantsPrefetching
872b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                            | DataSource::kIsCachingDataSource)) {
87350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    sp<MPEG4DataSource> cachedSource =
87450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                        new MPEG4DataSource(mDataSource);
87550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
87650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
87750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                        mDataSource = cachedSource;
87850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    }
87950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                }
8801edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber
8811edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber                mLastTrack->sampleTable = new SampleTable(mDataSource);
88250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            }
88350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
8846f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber            bool isTrack = false;
885bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (chunk_type == FOURCC('t', 'r', 'a', 'k')) {
8866f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                isTrack = true;
8876f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
888bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                Track *track = new Track;
889bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->next = NULL;
890bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                if (mLastTrack) {
891bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    mLastTrack->next = track;
892bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                } else {
893bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    mFirstTrack = track;
894bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                }
895bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                mLastTrack = track;
896bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
897bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->meta = new MetaData;
898bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->includes_expensive_metadata = false;
8996f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                track->skipTrack = false;
900bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->timescale = 0;
901bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->meta->setCString(kKeyMIMEType, "application/octet-stream");
902bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
903bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
904c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
90520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset;
90620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
90720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
90820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
90920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
91020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
91120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
91220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
913bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
914bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
915bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
916bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
9176f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber            if (isTrack) {
9186f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                if (mLastTrack->skipTrack) {
9196f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    Track *cur = mFirstTrack;
9206f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
9216f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    if (cur == mLastTrack) {
9226f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        delete cur;
9236f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        mFirstTrack = mLastTrack = NULL;
9246f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    } else {
9256f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        while (cur && cur->next != mLastTrack) {
9266f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                            cur = cur->next;
9276f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        }
9286f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        cur->next = NULL;
9296f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        delete mLastTrack;
9306f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        mLastTrack = cur;
9316f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    }
9326f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
9336f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    return OK;
9346f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                }
9356f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
936bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                status_t err = verifyTrack(mLastTrack);
937bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
938bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                if (err != OK) {
939bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    return err;
940bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                }
941bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
942bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                mInitCheck = OK;
94320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
944dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                if (!mIsDrm) {
945dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return UNKNOWN_ERROR;  // Return a dummy error.
946dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                } else {
947dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return OK;
948dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
94920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
95020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
95120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
95220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9530a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        case FOURCC('e', 'l', 's', 't'):
9540a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        {
9550517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
9560517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
9570a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            // See 14496-12 8.6.6
9580a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            uint8_t version;
9590a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (mDataSource->readAt(data_offset, &version, 1) < 1) {
9600a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                return ERROR_IO;
9610a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
9620a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9630a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            uint32_t entry_count;
9640a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (!mDataSource->getUInt32(data_offset + 4, &entry_count)) {
9650a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                return ERROR_IO;
9660a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
9670a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9680a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (entry_count != 1) {
9690a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                // we only support a single entry at the moment, for gapless playback
9700a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                ALOGW("ignoring edit list with %d entries", entry_count);
971fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            } else if (mHeaderTimescale == 0) {
972210efd48ed21ca0084d9440f9a1db7d9878f8094Marco Nelissen                ALOGW("ignoring edit list because timescale is 0");
9730a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            } else {
9740a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                off64_t entriesoffset = data_offset + 8;
9750a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                uint64_t segment_duration;
9760a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int64_t media_time;
9770a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9780a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                if (version == 1) {
9790a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    if (!mDataSource->getUInt64(entriesoffset, &segment_duration) ||
9800a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                            !mDataSource->getUInt64(entriesoffset + 8, (uint64_t*)&media_time)) {
9810a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        return ERROR_IO;
9820a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    }
9830a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                } else if (version == 0) {
9840a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    uint32_t sd;
9850a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int32_t mt;
9860a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    if (!mDataSource->getUInt32(entriesoffset, &sd) ||
9870a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                            !mDataSource->getUInt32(entriesoffset + 4, (uint32_t*)&mt)) {
9880a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        return ERROR_IO;
9890a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    }
9900a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    segment_duration = sd;
9910a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    media_time = mt;
9920a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                } else {
9930a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    return ERROR_IO;
9940a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                }
9950a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
996fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                uint64_t halfscale = mHeaderTimescale / 2;
997fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                segment_duration = (segment_duration * 1000000 + halfscale)/ mHeaderTimescale;
998fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                media_time = (media_time * 1000000 + halfscale) / mHeaderTimescale;
9990a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
10000a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int64_t duration;
10010a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int32_t samplerate;
10020a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                if (mLastTrack->meta->findInt64(kKeyDuration, &duration) &&
10030a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        mLastTrack->meta->findInt32(kKeySampleRate, &samplerate)) {
10040a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
10050a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t delay = (media_time  * samplerate + 500000) / 1000000;
10060a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
10070a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
10080a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t paddingus = duration - (segment_duration + media_time);
1009465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                    if (paddingus < 0) {
1010465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        // track duration from media header (which is what kKeyDuration is) might
1011465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        // be slightly shorter than the segment duration, which would make the
1012465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        // padding negative. Clamp to zero.
1013465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        paddingus = 0;
1014465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                    }
10150a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t paddingsamples = (paddingus * samplerate + 500000) / 1000000;
10160a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    mLastTrack->meta->setInt32(kKeyEncoderPadding, paddingsamples);
10170a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                }
10180a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
10190a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            break;
10200a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        }
10210a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
1022ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('f', 'r', 'm', 'a'):
1023ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
10240517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
10250517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
102648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t original_fourcc;
1027ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset, &original_fourcc, 4) < 4) {
1028ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1029ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1030ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            original_fourcc = ntohl(original_fourcc);
1031ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("read original format: %d", original_fourcc);
1032ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc));
103348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t num_channels = 0;
103448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t sample_rate = 0;
103548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (AdjustChannelsAndRate(original_fourcc, &num_channels, &sample_rate)) {
103648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
103748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
103848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            }
1039ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1040ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1041ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1042ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('t', 'e', 'n', 'c'):
1043ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
10440517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
10450517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1046ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (chunk_size < 32) {
1047ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1048ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1049ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1050ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // tenc box contains 1 byte version, 3 byte flags, 3 byte default algorithm id, one byte
1051ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // default IV size, 16 bytes default KeyID
1052ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // (ISO 23001-7)
1053ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            char buf[4];
1054ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memset(buf, 0, 4);
1055ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 4, buf + 1, 3) < 3) {
1056ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1057ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1058ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t defaultAlgorithmId = ntohl(*((int32_t*)buf));
1059ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (defaultAlgorithmId > 1) {
1060ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only 0 (clear) and 1 (AES-128) are valid
1061ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1062ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1063ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1064ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memset(buf, 0, 4);
1065ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 7, buf + 3, 1) < 1) {
1066ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1067ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1068ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t defaultIVSize = ntohl(*((int32_t*)buf));
1069ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1070ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((defaultAlgorithmId == 0 && defaultIVSize != 0) ||
1071ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    (defaultAlgorithmId != 0 && defaultIVSize == 0)) {
1072ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only unencrypted data must have 0 IV size
1073ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1074ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            } else if (defaultIVSize != 0 &&
1075ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    defaultIVSize != 8 &&
1076ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    defaultIVSize != 16) {
1077ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only supported sizes are 0, 8 and 16
1078ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1079ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1080ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1081ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint8_t defaultKeyId[16];
1082ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1083ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 8, &defaultKeyId, 16) < 16) {
1084ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1085ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1086ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1087ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setInt32(kKeyCryptoMode, defaultAlgorithmId);
1088ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setInt32(kKeyCryptoDefaultIVSize, defaultIVSize);
1089ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setData(kKeyCryptoKey, 'tenc', defaultKeyId, 16);
1090ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1091ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1092ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
109320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'k', 'h', 'd'):
109420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
10950517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
10960517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1097ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            status_t err;
1098ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) {
1099ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber                return err;
110020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
110120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
110220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
110320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
110420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1105ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('p', 's', 's', 'h'):
1106ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
11070517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
11080517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1109ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            PsshInfo pssh;
1110ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1111ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 4, &pssh.uuid, 16) < 16) {
1112ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1113ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1114ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1115ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t psshdatalen = 0;
1116ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 20, &psshdatalen, 4) < 4) {
1117ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1118ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1119ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            pssh.datalen = ntohl(psshdatalen);
1120ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("pssh data size: %d", pssh.datalen);
1121ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (pssh.datalen + 20 > chunk_size) {
1122ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // pssh data length exceeds size of containing box
1123ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1124ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1125ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
11268da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            pssh.data = new (std::nothrow) uint8_t[pssh.datalen];
11278da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            if (pssh.data == NULL) {
11288da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen                return ERROR_MALFORMED;
11298da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            }
1130ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("allocated pssh @ %p", pssh.data);
1131ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ssize_t requested = (ssize_t) pssh.datalen;
1132ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 24, pssh.data, requested) < requested) {
1133ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1134ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1135ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mPssh.push_back(pssh);
1136ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1137ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1138ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1139ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
114020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'h', 'd'):
114120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
11420517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
11430517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
114420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
114520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
114620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
114720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
114820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t version;
114934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
115020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, &version, sizeof(version))
115120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(version)) {
115220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
115320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
115420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1155c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t timescale_offset;
115620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
115720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
115820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 16;
115920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else if (version == 0) {
116020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 8;
116120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
116220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
116320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
116420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
116520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t timescale;
116634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
116720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        timescale_offset, &timescale, sizeof(timescale))
116820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(timescale)) {
116920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
117020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
117120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
117220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->timescale = ntohl(timescale);
117320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1174c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            // 14496-12 says all ones means indeterminate, but some files seem to use
1175c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            // 0 instead. We treat both the same.
117605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            int64_t duration = 0;
117720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
117834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
117920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration, sizeof(duration))
118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration)) {
118120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
118220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
1183c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (duration != -1) {
1184c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    duration = ntoh64(duration);
1185c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
118620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
118705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t duration32;
118834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
118920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration32, sizeof(duration32))
119020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration32)) {
119120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
119220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
119305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (duration32 != 0xffffffff) {
119405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    duration = ntohl(duration32);
119505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
119620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1197c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (duration != 0) {
1198c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mLastTrack->meta->setInt64(
1199c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                        kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
1200c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
120120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12027a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            uint8_t lang[2];
12037a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            off64_t lang_offset;
12047a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            if (version == 1) {
12057a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                lang_offset = timescale_offset + 4 + 8;
12067a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            } else if (version == 0) {
12077a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                lang_offset = timescale_offset + 4 + 4;
12087a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            } else {
12097a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                return ERROR_IO;
12107a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            }
12117a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
12127a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            if (mDataSource->readAt(lang_offset, &lang, sizeof(lang))
12137a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                    < (ssize_t)sizeof(lang)) {
12147a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                return ERROR_IO;
12157a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            }
12167a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
12177a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // To get the ISO-639-2/T three character language code
12187a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // 1 bit pad followed by 3 5-bits characters. Each character
12197a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // is packed as the difference between its ASCII value and 0x60.
12207a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            char lang_code[4];
12217a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[0] = ((lang[0] >> 2) & 0x1f) + 0x60;
12227a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[1] = ((lang[0] & 0x3) << 3 | (lang[1] >> 5)) + 0x60;
12237a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[2] = (lang[1] & 0x1f) + 0x60;
12247a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[3] = '\0';
12257a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
12267a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            mLastTrack->meta->setCString(
12277a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                    kKeyMediaLanguage, lang_code);
12287a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
122920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
123020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
123120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
123220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'd'):
123320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
123420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 8) {
123520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
123620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
123720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
123820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8];
1239c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size < (off64_t)sizeof(buffer)) {
1240bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1241bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
1242bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
124334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
124420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, 8) < 8) {
124520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
124620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
124720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
124820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
124920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
125020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
125120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
125220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
125320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t entry_count = U32_AT(&buffer[4]);
125420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
125520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (entry_count > 1) {
12563b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // For 3GPP timed text, there could be multiple tx3g boxes contain
12573b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // multiple text display formats. These formats will be used to
12583b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // display the timed text.
1259ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // For encrypted files, there may also be more than one entry.
12603b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                const char *mime;
12613b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1262ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) &&
1263ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                        strcasecmp(mime, "application/octet-stream")) {
12643b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    // For now we only support a single type of media per track.
12653b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    mLastTrack->skipTrack = true;
12663b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    *offset += chunk_size;
12673b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    break;
12683b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                }
126920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1270c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
127120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + 8;
127220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            for (uint32_t i = 0; i < entry_count; ++i) {
127320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
127420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
127520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
127620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
127720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1278bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1279bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1280bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1281bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
128220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
128320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
128420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
128520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
128648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        case FOURCC('e', 'n', 'c', 'a'):
128720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
1288371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
128920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
129020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8 + 20];
129120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
129220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic AudioSampleEntry size.
129320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
129420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
129520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
129634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
129720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
129820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
129920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
130020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
130120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
130248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t num_channels = U16_AT(&buffer[16]);
130320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
130481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint16_t sample_size = U16_AT(&buffer[18]);
130581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
130681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
130748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (chunk_type != FOURCC('e', 'n', 'c', 'a')) {
130848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                // if the chunk type is enca, we'll get the type from the sinf/frma box later
130948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
131048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate);
131120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
131248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            ALOGV("*** coding='%s' %d channels, size %d, rate %d\n",
131381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                   chunk, num_channels, sample_size, sample_rate);
131420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
131520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
131620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1317c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
131820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
131920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
132020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
132120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
132220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
132320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
132420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1325bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1326bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1327bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1328bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
132920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
133020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
133120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
133220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
1333ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('e', 'n', 'c', 'v'):
133420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
1335e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('H', '2', '6', '3'):
1336e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('h', '2', '6', '3'):
133720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
13383b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'v', 'c', '1'):
13393b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'e', 'v', '1'):
134020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
13417be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber            mHasVideo = true;
13427be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
134320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[78];
134420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
134520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic VideoSampleEntry size.
134620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
134720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
134820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
134934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
135020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
135120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
135220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
135320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
135420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
135520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t width = U16_AT(&buffer[6 + 18]);
135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t height = U16_AT(&buffer[6 + 20]);
135720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1358ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // The video sample is not standard-compliant if it has invalid dimension.
1359a6256238d9015c42129fe43791968768fe501efaJames Dong            // Use some default width and height value, and
1360a6256238d9015c42129fe43791968768fe501efaJames Dong            // let the decoder figure out the actual width and height (and thus
1361a6256238d9015c42129fe43791968768fe501efaJames Dong            // be prepared for INFO_FOMRAT_CHANGED event).
1362a6256238d9015c42129fe43791968768fe501efaJames Dong            if (width == 0)  width  = 352;
1363a6256238d9015c42129fe43791968768fe501efaJames Dong            if (height == 0) height = 288;
1364a6256238d9015c42129fe43791968768fe501efaJames Dong
1365134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            // printf("*** coding='%s' width=%d height=%d\n",
1366134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            //        chunk, width, height);
136720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1368ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (chunk_type != FOURCC('e', 'n', 'c', 'v')) {
1369ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // if the chunk type is encv, we'll get the type from the sinf/frma box later
1370ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
1371ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
137220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyWidth, width);
137320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyHeight, height);
137420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1375c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
137620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
137720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
137820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
137920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
138020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
138120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
138220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1383bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1384bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1385bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1386bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
138720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
138820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
138920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
139020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'c', 'o'):
139120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('c', 'o', '6', '4'):
139220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
139320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
139420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setChunkOffsetParams(
139520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
139620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13970517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
13980517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
139920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
140020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
140120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
140220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
140320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
140420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
140520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
140620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'c'):
140720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
140820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
140920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleToChunkParams(
141020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
141120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14120517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
14130517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
141420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
141520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
141620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
141720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
141820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
141920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
142020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
142120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'z'):
142220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'z', '2'):
142320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
142420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
142520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleSizeParams(
142620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
142720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14280517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
14290517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
143020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
143120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
143220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
143320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1434738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            size_t max_size;
143549110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            err = mLastTrack->sampleTable->getMaxSampleSize(&max_size);
143649110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber
143749110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            if (err != OK) {
143849110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber                return err;
143949110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            }
1440738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber
144105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (max_size != 0) {
144205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // Assume that a given buffer only contains at most 10 chunks,
144305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // each chunk originally prefixed with a 2 byte length will
144405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
144505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // and thus will grow by 2 bytes per chunk.
144605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
144705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            } else {
144805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // No size was specified. Pick a conservatively large size.
144905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                int32_t width, height;
1450f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                if (!mLastTrack->meta->findInt32(kKeyWidth, &width) ||
1451f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    !mLastTrack->meta->findInt32(kKeyHeight, &height)) {
145205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ALOGE("No width or height, assuming worst case 1080p");
1453f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    width = 1920;
1454f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    height = 1080;
145505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
1456f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar
14574256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen                const char *mime;
14584256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1459f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
1460f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // AVC requires compression ratio of at least 2, and uses
1461f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // macroblocks
1462f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    max_size = ((width + 15) / 16) * ((height + 15) / 16) * 192;
1463f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                } else {
1464f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // For all other formats there is no minimum compression
1465f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // ratio. Use compression ratio of 1.
1466f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    max_size = width * height * 3 / 2;
146705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
1468f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size);
146905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
1470113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong
14714256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            // NOTE: setting another piece of metadata invalidates any pointers (such as the
14724256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            // mimetype) previously obtained, so don't cache them.
1473113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            const char *mime;
1474113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1475113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            // Calculate average frame rate.
1476113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            if (!strncasecmp("video/", mime, 6)) {
1477113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                size_t nSamples = mLastTrack->sampleTable->countSamples();
1478113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                int64_t durationUs;
1479113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                if (mLastTrack->meta->findInt64(kKeyDuration, &durationUs)) {
1480113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                    if (durationUs > 0) {
1481113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                        int32_t frameRate = (nSamples * 1000000LL +
1482113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                                    (durationUs >> 1)) / durationUs;
1483113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                        mLastTrack->meta->setInt32(kKeyFrameRate, frameRate);
1484113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                    }
1485113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                }
1486113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            }
1487113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong
148820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
148920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
149020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
149120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 't', 's'):
149220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
14930517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
14940517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
149520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
149620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setTimeToSampleParams(
149720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
149820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
149920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
150020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
150120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
150220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
150320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
150420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
150520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15064931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        case FOURCC('c', 't', 't', 's'):
15074931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        {
15080517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
15090517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
15104931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            status_t err =
15114931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                mLastTrack->sampleTable->setCompositionTimeToSampleParams(
15124931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                        data_offset, chunk_data_size);
15134931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
15144931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            if (err != OK) {
15154931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                return err;
15164931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            }
15174931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
15184931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            break;
15194931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        }
15204931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
152120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 's'):
152220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
15230517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
15240517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
152520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
152620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSyncSampleParams(
152720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
152820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
152920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
153020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
153120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
153220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
153320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
153420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
153520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15364948818cb91176df74c972ac27b2f392b5d148bcJames Dong        // @xyz
15374948818cb91176df74c972ac27b2f392b5d148bcJames Dong        case FOURCC('\xA9', 'x', 'y', 'z'):
15384948818cb91176df74c972ac27b2f392b5d148bcJames Dong        {
15390517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
15400517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
15414948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Best case the total data length inside "@xyz" box
15424948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // would be 8, for instance "@xyz" + "\x00\x04\x15\xc7" + "0+0/",
15434948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // where "\x00\x04" is the text string length with value = 4,
15444948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // "\0x15\xc7" is the language code = en, and "0+0" is a
15454948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // location (string) value with longitude = 0 and latitude = 0.
15464948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (chunk_data_size < 8) {
15474948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_MALFORMED;
15484948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
15494948818cb91176df74c972ac27b2f392b5d148bcJames Dong
15504948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Worst case the location string length would be 18,
15514948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // for instance +90.0000-180.0000, without the trailing "/" and
15524948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // the string length + language code.
15534948818cb91176df74c972ac27b2f392b5d148bcJames Dong            char buffer[18];
15544948818cb91176df74c972ac27b2f392b5d148bcJames Dong
15554948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Substracting 5 from the data size is because the text string length +
15564948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // language code takes 4 bytes, and the trailing slash "/" takes 1 byte.
15574948818cb91176df74c972ac27b2f392b5d148bcJames Dong            off64_t location_length = chunk_data_size - 5;
15584948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (location_length >= (off64_t) sizeof(buffer)) {
15594948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_MALFORMED;
15604948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
15614948818cb91176df74c972ac27b2f392b5d148bcJames Dong
15624948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (mDataSource->readAt(
15634948818cb91176df74c972ac27b2f392b5d148bcJames Dong                        data_offset + 4, buffer, location_length) < location_length) {
15644948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_IO;
15654948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
15664948818cb91176df74c972ac27b2f392b5d148bcJames Dong
15674948818cb91176df74c972ac27b2f392b5d148bcJames Dong            buffer[location_length] = '\0';
15684948818cb91176df74c972ac27b2f392b5d148bcJames Dong            mFileMetaData->setCString(kKeyLocation, buffer);
15694948818cb91176df74c972ac27b2f392b5d148bcJames Dong            break;
15704948818cb91176df74c972ac27b2f392b5d148bcJames Dong        }
15714948818cb91176df74c972ac27b2f392b5d148bcJames Dong
157220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('e', 's', 'd', 's'):
157320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
15740517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
15750517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
157620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
157720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
157820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
157920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
158020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[256];
1581c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size > (off64_t)sizeof(buffer)) {
158220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
158320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
158420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
158534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
158620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
158720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
158820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
158920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
159020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
159120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
159220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
159320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
159420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
159520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
159620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
159720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1598ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            if (mPath.size() >= 2
1599ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
1600ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // Information from the ESDS must be relied on for proper
1601ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // setup of sample rate and channel count for MPEG4 Audio.
1602ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // The generic header appears to only contain generic
1603ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // information...
1604ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1605ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio(
1606ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                        &buffer[4], chunk_data_size - 4);
1607ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1608ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                if (err != OK) {
1609ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    return err;
1610ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                }
1611ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            }
1612ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
161320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
161420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
161520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
161620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', 'C'):
161720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
16180517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
16190517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1620d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson            sp<ABuffer> buffer = new ABuffer(chunk_data_size);
162120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
162234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
1623d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson                        data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
162420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
162520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
162620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
162720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
1628d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson                    kKeyAVCC, kTypeAVCC, buffer->data(), chunk_data_size);
162920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
163020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
163120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
16323b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        case FOURCC('h', 'v', 'c', 'C'):
16333b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        {
16343b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            sp<ABuffer> buffer = new ABuffer(chunk_data_size);
16353b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
16363b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            if (mDataSource->readAt(
16373b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar                        data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
16383b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar                return ERROR_IO;
16393b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            }
16403b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
16413b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            mLastTrack->meta->setData(
16423b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar                    kKeyHVCC, kTypeHVCC, buffer->data(), chunk_data_size);
16433b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
16443b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            *offset += chunk_size;
16453b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            break;
16463b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        }
164720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1648244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        case FOURCC('d', '2', '6', '3'):
1649244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        {
16500517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
165117e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            /*
165217e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * d263 contains a fixed 7 bytes part:
165317e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   vendor - 4 bytes
165417e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   version - 1 byte
165517e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   level - 1 byte
165617e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   profile - 1 byte
165717e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * optionally, "d263" box itself may contain a 16-byte
165817e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * bit rate box (bitr)
165917e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   average bit rate - 4 bytes
166017e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   max bit rate - 4 bytes
166117e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             */
166217e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            char buffer[23];
166317e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            if (chunk_data_size != 7 &&
166417e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong                chunk_data_size != 23) {
166529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Incorrect D263 box size %lld", chunk_data_size);
1666244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                return ERROR_MALFORMED;
1667244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            }
1668244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1669244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            if (mDataSource->readAt(
1670244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                    data_offset, buffer, chunk_data_size) < chunk_data_size) {
1671244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                return ERROR_IO;
1672244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            }
1673244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1674244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size);
1675244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1676244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            break;
1677244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        }
1678244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
167972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'e', 't', 'a'):
168072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
168172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            uint8_t buffer[4];
1682c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size < (off64_t)sizeof(buffer)) {
16830517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen                *offset += chunk_size;
1684bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1685bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
1686bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
168772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
168872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, buffer, 4) < 4) {
16890517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen                *offset += chunk_size;
169072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
169172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
169272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
169372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (U32_AT(buffer) != 0) {
169472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                // Should be version 0, flags 0.
1695ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
1696ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // If it's not, let's assume this is one of those
1697ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // apparently malformed chunks that don't have flags
1698ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // and completely different semantics than what's
1699ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // in the MPEG4 specs and skip it.
1700ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                *offset += chunk_size;
1701ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                return OK;
170272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
170372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1704c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
170572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset = data_offset + sizeof(buffer);
170672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            while (*offset < stop_offset) {
170772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                status_t err = parseChunk(offset, depth + 1);
170872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
170972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
171072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
171172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
1712bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1713bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1714bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1715bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
171672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
171772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
171872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
17195d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('m', 'e', 'a', 'n'):
17205d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('n', 'a', 'm', 'e'):
172172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('d', 'a', 't', 'a'):
172272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
17230517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
17240517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
172572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mPath.size() == 6 && underMetaDataPath(mPath)) {
1726fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                status_t err = parseITunesMetaData(data_offset, chunk_data_size);
172772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
172872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
172972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
173072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
173172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
173272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
173372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
173472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
173572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
173672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'v', 'h', 'd'):
173772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
17380517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
17390517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1740c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (chunk_data_size < 32) {
174172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_MALFORMED;
174272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
174372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1744c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            uint8_t header[32];
174572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
174672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, header, sizeof(header))
174772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    < (ssize_t)sizeof(header)) {
174872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
174972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
175072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1751fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            uint64_t creationTime;
1752c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            uint64_t duration = 0;
175372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (header[0] == 1) {
175472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U64_AT(&header[4]);
1755fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                mHeaderTimescale = U32_AT(&header[20]);
1756c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                duration = U64_AT(&header[24]);
1757c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (duration == 0xffffffffffffffff) {
1758c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    duration = 0;
1759c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1760bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (header[0] != 0) {
1761bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
176272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            } else {
176372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U32_AT(&header[4]);
1764fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                mHeaderTimescale = U32_AT(&header[12]);
1765c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                uint32_t d32 = U32_AT(&header[16]);
1766c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (d32 == 0xffffffff) {
1767c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    d32 = 0;
1768c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1769c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                duration = d32;
1770c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1771c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (duration != 0) {
1772c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mFileMetaData->setInt64(kKeyDuration, duration * 1000000 / mHeaderTimescale);
177372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
177472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
177572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            String8 s;
177672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            convertTimeToDate(creationTime, &s);
177772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
177872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(kKeyDate, s.string());
177972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
178072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
178172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
178272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1783c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        case FOURCC('m', 'e', 'h', 'd'):
1784c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        {
1785c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            *offset += chunk_size;
1786c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1787c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (chunk_data_size < 8) {
1788c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_MALFORMED;
1789c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1790c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1791c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            uint8_t flags[4];
1792c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (mDataSource->readAt(
1793c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                        data_offset, flags, sizeof(flags))
1794c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    < (ssize_t)sizeof(flags)) {
1795c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_IO;
1796c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1797c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1798c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            uint64_t duration = 0;
1799c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (flags[0] == 1) {
1800c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                // 64 bit
1801c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (chunk_data_size < 12) {
1802c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    return ERROR_MALFORMED;
1803c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1804c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mDataSource->getUInt64(data_offset + 4, &duration);
1805c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (duration == 0xffffffffffffffff) {
1806c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    duration = 0;
1807c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1808c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            } else if (flags[0] == 0) {
1809c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                // 32 bit
1810c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                uint32_t d32;
1811c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mDataSource->getUInt32(data_offset + 4, &d32);
1812c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                if (d32 == 0xffffffff) {
1813c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                    d32 = 0;
1814c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                }
1815c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                duration = d32;
1816c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            } else {
1817c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_MALFORMED;
1818c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1819c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1820c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (duration != 0) {
1821c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                mFileMetaData->setInt64(kKeyDuration, duration * 1000000 / mHeaderTimescale);
1822c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1823c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1824c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            break;
1825c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        }
1826c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1827dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        case FOURCC('m', 'd', 'a', 't'):
1828dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        {
1829ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("mdat chunk, drm: %d", mIsDrm);
1830dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (!mIsDrm) {
1831dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                *offset += chunk_size;
1832dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                break;
1833dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
1834dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
1835dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (chunk_size < 8) {
1836dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
1837dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
1838dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
1839dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return parseDrmSINF(offset, data_offset);
1840dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
1841dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
18423b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        case FOURCC('h', 'd', 'l', 'r'):
18433b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        {
18440517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
18450517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
18463b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t buffer;
18473b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (mDataSource->readAt(
18483b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                        data_offset + 8, &buffer, 4) < 4) {
18493b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_IO;
18503b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
18513b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
18523b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type = ntohl(buffer);
18533b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            // For the 3GPP file format, the handler-type within the 'hdlr' box
1854e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            // shall be 'text'. We also want to support 'sbtl' handler type
1855e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            // for a practical reason as various MPEG4 containers use it.
1856e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            if (type == FOURCC('t', 'e', 'x', 't') || type == FOURCC('s', 'b', 't', 'l')) {
18573b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
18583b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
18593b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
18603b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            break;
18613b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        }
18623b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
1863c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        case FOURCC('t', 'r', 'e', 'x'):
1864c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        {
1865c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            *offset += chunk_size;
1866c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
1867c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (chunk_data_size < 24) {
1868c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_IO;
1869c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1870c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            uint32_t duration;
1871c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            Trex trex;
1872c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (!mDataSource->getUInt32(data_offset + 4, &trex.track_ID) ||
1873c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                !mDataSource->getUInt32(data_offset + 8, &trex.default_sample_description_index) ||
1874c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                !mDataSource->getUInt32(data_offset + 12, &trex.default_sample_duration) ||
1875c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                !mDataSource->getUInt32(data_offset + 16, &trex.default_sample_size) ||
1876c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                !mDataSource->getUInt32(data_offset + 20, &trex.default_sample_flags)) {
1877c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                return ERROR_IO;
1878c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
1879c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            mTrex.add(trex);
1880c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            break;
1881c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        }
1882c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
18837a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        case FOURCC('t', 'x', '3', 'g'):
18847a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        {
18853b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type;
18863b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            const void *data;
18873b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            size_t size = 0;
18883b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (!mLastTrack->meta->findData(
18893b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    kKeyTextFormatData, &type, &data, &size)) {
18903b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                size = 0;
18913b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
18923b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
1893e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake            if (SIZE_MAX - chunk_size <= size) {
1894e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake                return ERROR_MALFORMED;
1895e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake            }
1896e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake
18978da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            uint8_t *buffer = new (std::nothrow) uint8_t[size + chunk_size];
18988da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            if (buffer == NULL) {
18998da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen                return ERROR_MALFORMED;
19008da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen            }
19013b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
19023b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (size > 0) {
19033b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                memcpy(buffer, data, size);
19043b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
19053b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
19063b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size))
19073b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    < chunk_size) {
19083b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                delete[] buffer;
19093b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                buffer = NULL;
19103b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
19110517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen                // advance read pointer so we don't end up reading this again
19120517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen                *offset += chunk_size;
19133b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_IO;
19143b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
19153b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
19163b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            mLastTrack->meta->setData(
19173b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    kKeyTextFormatData, 0, buffer, size + chunk_size);
19183b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
19193b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            delete[] buffer;
19207a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
19217a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            *offset += chunk_size;
19227a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            break;
19237a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        }
19247a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
1925515e855eae78aa495da58356486aaa666cb57fd1James Dong        case FOURCC('c', 'o', 'v', 'r'):
1926515e855eae78aa495da58356486aaa666cb57fd1James Dong        {
19270517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
19280517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1929515e855eae78aa495da58356486aaa666cb57fd1James Dong            if (mFileMetaData != NULL) {
19303856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("chunk_data_size = %lld and data_offset = %lld",
1931515e855eae78aa495da58356486aaa666cb57fd1James Dong                        chunk_data_size, data_offset);
193205ddc499b9d50c90f552ed1333110f28a1406e7cJoshua J. Drake
193305ddc499b9d50c90f552ed1333110f28a1406e7cJoshua J. Drake                if (chunk_data_size >= SIZE_MAX - 1) {
193405ddc499b9d50c90f552ed1333110f28a1406e7cJoshua J. Drake                    return ERROR_MALFORMED;
193505ddc499b9d50c90f552ed1333110f28a1406e7cJoshua J. Drake                }
19361552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1);
1937515e855eae78aa495da58356486aaa666cb57fd1James Dong                if (mDataSource->readAt(
19381552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                    data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) {
1939515e855eae78aa495da58356486aaa666cb57fd1James Dong                    return ERROR_IO;
1940515e855eae78aa495da58356486aaa666cb57fd1James Dong                }
1941515e855eae78aa495da58356486aaa666cb57fd1James Dong                const int kSkipBytesOfDataBox = 16;
19424a492bf2ac47b9844d2527e1fcdf0064c3d8d52eJoshua J. Drake                if (chunk_data_size <= kSkipBytesOfDataBox) {
19434a492bf2ac47b9844d2527e1fcdf0064c3d8d52eJoshua J. Drake                    return ERROR_MALFORMED;
19444a492bf2ac47b9844d2527e1fcdf0064c3d8d52eJoshua J. Drake                }
19454a492bf2ac47b9844d2527e1fcdf0064c3d8d52eJoshua J. Drake
1946515e855eae78aa495da58356486aaa666cb57fd1James Dong                mFileMetaData->setData(
1947515e855eae78aa495da58356486aaa666cb57fd1James Dong                    kKeyAlbumArt, MetaData::TYPE_NONE,
19481552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                    buffer->data() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox);
1949515e855eae78aa495da58356486aaa666cb57fd1James Dong            }
1950515e855eae78aa495da58356486aaa666cb57fd1James Dong
1951515e855eae78aa495da58356486aaa666cb57fd1James Dong            break;
1952515e855eae78aa495da58356486aaa666cb57fd1James Dong        }
1953515e855eae78aa495da58356486aaa666cb57fd1James Dong
1954fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('t', 'i', 't', 'l'):
1955fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('p', 'e', 'r', 'f'):
1956fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'u', 't', 'h'):
1957fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('g', 'n', 'r', 'e'):
1958fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'l', 'b', 'm'):
1959fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('y', 'r', 'r', 'c'):
1960fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
19610517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
19620517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1963fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            status_t err = parse3GPPMetaData(data_offset, chunk_data_size, depth);
1964fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
1965fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (err != OK) {
1966fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                return err;
1967fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
1968fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
1969fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
1970fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
1971fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
1972328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        case FOURCC('I', 'D', '3', '2'):
1973328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        {
19740517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen            *offset += chunk_size;
19750517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen
1976328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            if (chunk_data_size < 6) {
1977328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                return ERROR_MALFORMED;
1978328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            }
1979328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
1980328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            parseID3v2MetaData(data_offset + 6);
1981328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
1982328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            break;
1983328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        }
1984328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
19855d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('-', '-', '-', '-'):
19865d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        {
19875d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentMean.clear();
19885d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentName.clear();
19895d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentData.clear();
19905d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            *offset += chunk_size;
19915d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            break;
19925d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        }
19935d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen
199405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('s', 'i', 'd', 'x'):
199505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        {
199605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            parseSegmentIndex(data_offset, chunk_data_size);
199705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset += chunk_size;
199805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return UNKNOWN_ERROR; // stop parsing after sidx
199905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
200005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
200120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
200220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
200320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
200420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
200520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
200620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
200720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
200820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
200920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
201020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
201105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) {
201205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen  ALOGV("MPEG4Extractor::parseSegmentIndex");
201305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
201405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 12) {
201505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      return -EINVAL;
201605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
201705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
201805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
201905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) {
202005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
202105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
202205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
202305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t version = flags >> 24;
202405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    flags &= 0xffffff;
202505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
202605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx version %d", version);
202705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
202805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t referenceId;
202905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, &referenceId)) {
203005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
203105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
203205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
203305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t timeScale;
203405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 8, &timeScale)) {
203505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
203605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
203705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx refid/timescale: %d/%d", referenceId, timeScale);
203805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
203905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t earliestPresentationTime;
204005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t firstOffset;
204105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
204205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 12;
204305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 12;
204405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
204505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (version == 0) {
204605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 8) {
204705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
204805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
204905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t tmp;
205005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
205105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
205205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
205305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        earliestPresentationTime = tmp;
205405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset + 4, &tmp)) {
205505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
205605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
205705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        firstOffset = tmp;
205805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 8;
205905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 8;
206005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
206105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 16) {
206205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
206305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
206405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset, &earliestPresentationTime)) {
206505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
206605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
206705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset + 8, &firstOffset)) {
206805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
206905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
207005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 16;
207105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 16;
207205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
2073a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("sidx pres/off: %" PRIu64 "/%" PRIu64, earliestPresentationTime, firstOffset);
207405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
207505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 4) {
207605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
207705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
207805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
207905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint16_t referenceCount;
208005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt16(offset + 2, &referenceCount)) {
208105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
208205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
208305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 4;
208405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 4;
208505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("refcount: %d", referenceCount);
208605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
208705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < referenceCount * 12) {
208805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
208905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
209005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
209105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t total_duration = 0;
209205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    for (unsigned int i = 0; i < referenceCount; i++) {
209305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t d1, d2, d3;
209405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
209505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &d1) ||     // size
209605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            !mDataSource->getUInt32(offset + 4, &d2) || // duration
209705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            !mDataSource->getUInt32(offset + 8, &d3)) { // flags
209805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
209905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
210005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
210105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (d1 & 0x80000000) {
210205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGW("sub-sidx boxes not supported yet");
210305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
210405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool sap = d3 & 0x80000000;
21053f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen        uint32_t saptype = (d3 >> 28) & 7;
21063f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen        if (!sap || (saptype != 1 && saptype != 2)) {
21073f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            // type 1 and 2 are sync samples
21083f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            ALOGW("not a stream access point, or unsupported type: %08x", d3);
210905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
211005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        total_duration += d2;
211105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 12;
211205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV(" item %d, %08x %08x %08x", i, d1, d2, d3);
211305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        SidxEntry se;
211405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        se.mSize = d1 & 0x7fffffff;
211505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        se.mDurationUs = 1000000LL * d2 / timeScale;
211605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mSidxEntries.add(se);
211705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
211805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2119c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    uint64_t sidxDuration = total_duration * 1000000 / timeScale;
212005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
212105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t metaDuration;
212205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mLastTrack->meta->findInt64(kKeyDuration, &metaDuration) || metaDuration == 0) {
2123c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        mLastTrack->meta->setInt64(kKeyDuration, sidxDuration);
212405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
212505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
212605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
212705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
212805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
212905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2130ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huberstatus_t MPEG4Extractor::parseTrackHeader(
2131c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t data_offset, off64_t data_size) {
2132ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (data_size < 4) {
2133ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_MALFORMED;
2134ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2135ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2136ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint8_t version;
2137ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (mDataSource->readAt(data_offset, &version, 1) < 1) {
2138ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_IO;
2139ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2140ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2141ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    size_t dynSize = (version == 1) ? 36 : 24;
2142ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2143ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint8_t buffer[36 + 60];
2144ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2145c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    if (data_size != (off64_t)dynSize + 60) {
2146ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_MALFORMED;
2147ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2148ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2149ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (mDataSource->readAt(
2150ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber                data_offset, buffer, data_size) < (ssize_t)data_size) {
2151ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_IO;
2152ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2153ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2154ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint64_t ctime, mtime, duration;
2155ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t id;
2156ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2157ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (version == 1) {
2158ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        ctime = U64_AT(&buffer[4]);
2159ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mtime = U64_AT(&buffer[12]);
2160ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        id = U32_AT(&buffer[20]);
2161ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        duration = U64_AT(&buffer[28]);
216204022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen    } else if (version == 0) {
2163ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        ctime = U32_AT(&buffer[4]);
2164ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mtime = U32_AT(&buffer[8]);
2165ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        id = U32_AT(&buffer[12]);
2166ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        duration = U32_AT(&buffer[20]);
216704022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen    } else {
216804022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen        return ERROR_UNSUPPORTED;
2169ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2170ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2171ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    mLastTrack->meta->setInt32(kKeyTrackID, id);
2172ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2173ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    size_t matrixOffset = dynSize + 16;
2174ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a00 = U32_AT(&buffer[matrixOffset]);
2175ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a01 = U32_AT(&buffer[matrixOffset + 4]);
2176ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t dx = U32_AT(&buffer[matrixOffset + 8]);
2177ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a10 = U32_AT(&buffer[matrixOffset + 12]);
2178ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a11 = U32_AT(&buffer[matrixOffset + 16]);
2179ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t dy = U32_AT(&buffer[matrixOffset + 20]);
2180ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2181ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#if 0
2182df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("x' = %.2f * x + %.2f * y + %.2f",
2183ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber         a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f);
2184df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("y' = %.2f * x + %.2f * y + %.2f",
2185ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber         a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f);
2186ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#endif
2187ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2188ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t rotationDegrees;
2189ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2190ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    static const int32_t kFixedOne = 0x10000;
2191ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) {
2192ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        // Identity, no rotation
2193ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 0;
2194ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) {
2195ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 90;
2196ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) {
2197ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 270;
2198ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) {
2199ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 180;
2200ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else {
22015ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("We only support 0,90,180,270 degree rotation matrices");
2202ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 0;
2203ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2204ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2205ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (rotationDegrees != 0) {
2206ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees);
2207ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2208ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2209b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    // Handle presentation display size, which could be different
2210b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    // from the image size indicated by kKeyWidth and kKeyHeight.
2211ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t width = U32_AT(&buffer[dynSize + 52]);
2212ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t height = U32_AT(&buffer[dynSize + 56]);
2213b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    mLastTrack->meta->setInt32(kKeyDisplayWidth, width >> 16);
2214b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    mLastTrack->meta->setInt32(kKeyDisplayHeight, height >> 16);
2215ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2216ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    return OK;
2217ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber}
2218ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2219fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhéstatus_t MPEG4Extractor::parseITunesMetaData(off64_t offset, size_t size) {
2220c570778430a22b5488cae72982cf9fb8033dbda3Nick Kralevich    if (size < 4 || size == SIZE_MAX) {
222172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_MALFORMED;
222272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
222372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
22248da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    uint8_t *buffer = new (std::nothrow) uint8_t[size + 1];
22258da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    if (buffer == NULL) {
22268da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        return ERROR_MALFORMED;
22278da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    }
222872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (mDataSource->readAt(
222972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                offset, buffer, size) != (ssize_t)size) {
223072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        delete[] buffer;
223172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        buffer = NULL;
223272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
223372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_IO;
223472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
223572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
223672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t flags = U32_AT(buffer);
223772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
223872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t metadataKey = 0;
22395d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    char chunk[5];
22405d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    MakeFourCCString(mPath[4], chunk);
22415d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    ALOGV("meta: %s @ %lld", chunk, offset);
224272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    switch (mPath[4]) {
224372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'a', 'l', 'b'):
224472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
224572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbum;
224672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
224772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
224872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'A', 'R', 'T'):
224972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
225072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyArtist;
225172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
225272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
225366ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        case FOURCC('a', 'A', 'R', 'T'):
225466ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        {
225566ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            metadataKey = kKeyAlbumArtist;
225666ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            break;
225766ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        }
225872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'd', 'a', 'y'):
225972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
226072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyYear;
226172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
226272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
226372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'n', 'a', 'm'):
226472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
226572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyTitle;
226672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
226772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
226872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'w', 'r', 't'):
226972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
227072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyWriter;
227172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
227272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
227372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('c', 'o', 'v', 'r'):
227472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
227572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbumArt;
227672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
227772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
227872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('g', 'n', 'r', 'e'):
227972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
228072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyGenre;
228172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
228272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
228326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC(0xa9, 'g', 'e', 'n'):
228426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
228526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            metadataKey = kKeyGenre;
228626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
228726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
228811f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        case FOURCC('c', 'p', 'i', 'l'):
228911f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        {
229011f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            if (size == 9 && flags == 21) {
229111f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                char tmp[16];
229211f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                sprintf(tmp, "%d",
229311f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                        (int)buffer[size - 1]);
229411f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen
229511f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                mFileMetaData->setCString(kKeyCompilation, tmp);
229611f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            }
229711f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            break;
229811f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        }
229972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('t', 'r', 'k', 'n'):
230072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
230172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (size == 16 && flags == 0) {
230272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char tmp[16];
2303afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTrack = (uint16_t*)&buffer[10];
2304afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTotalTracks = (uint16_t*)&buffer[12];
2305afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                sprintf(tmp, "%d/%d", ntohs(*pTrack), ntohs(*pTotalTracks));
230672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
230772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
230872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
230972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
231072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
231126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC('d', 'i', 's', 'k'):
231226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
2313afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik            if ((size == 14 || size == 16) && flags == 0) {
231426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                char tmp[16];
2315afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pDisc = (uint16_t*)&buffer[10];
2316afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTotalDiscs = (uint16_t*)&buffer[12];
2317afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                sprintf(tmp, "%d/%d", ntohs(*pDisc), ntohs(*pTotalDiscs));
231826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
231926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(kKeyDiscNumber, tmp);
232026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            }
232126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
232226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
23235d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('-', '-', '-', '-'):
23245d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        {
23255d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            buffer[size] = '\0';
23265d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            switch (mPath[5]) {
23275d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('m', 'e', 'a', 'n'):
23285d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentMean.setTo((const char *)buffer + 4);
23295d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
23305d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('n', 'a', 'm', 'e'):
23315d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentName.setTo((const char *)buffer + 4);
23325d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
23335d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('d', 'a', 't', 'a'):
23345d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentData.setTo((const char *)buffer + 8);
23355d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
23365d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            }
23378c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
23388c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // Once we have a set of mean/name/data info, go ahead and process
23398c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // it to see if its something we are interested in.  Whether or not
23408c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // were are interested in the specific tag, make sure to clear out
23418c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // the set so we can be ready to process another tuple should one
23428c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // show up later in the file.
23438c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            if ((mLastCommentMean.length() != 0) &&
23448c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                (mLastCommentName.length() != 0) &&
23458c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                (mLastCommentData.length() != 0)) {
23468c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
23478c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                if (mLastCommentMean == "com.apple.iTunes"
23488c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        && mLastCommentName == "iTunSMPB") {
23498c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    int32_t delay, padding;
23508c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    if (sscanf(mLastCommentData,
23518c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                               " %*x %x %x %*x", &delay, &padding) == 2) {
23528c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
23538c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        mLastTrack->meta->setInt32(kKeyEncoderPadding, padding);
23548c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    }
23555d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                }
23568c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
23575d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentMean.clear();
23585d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentName.clear();
23595d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentData.clear();
23605d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            }
23615d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            break;
23625d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        }
236326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
236472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        default:
236572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
236672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
236772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
2368328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    if (size >= 8 && metadataKey && !mFileMetaData->hasData(metadataKey)) {
236972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        if (metadataKey == kKeyAlbumArt) {
237072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setData(
237172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    kKeyAlbumArt, MetaData::TYPE_NONE,
237272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    buffer + 8, size - 8);
237372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else if (metadataKey == kKeyGenre) {
237472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (flags == 0) {
237526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // uint8_t genre code, iTunes genre codes are
237626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // the standard id3 codes, except they start
237726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // at 1 instead of 0 (e.g. Pop is 14, not 13)
237826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // We use standard id3 numbering, so subtract 1.
237926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                int genrecode = (int)buffer[size - 1];
238026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                genrecode--;
238126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                if (genrecode < 0) {
238226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                    genrecode = 255; // reserved for 'unknown genre'
238326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                }
238472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char genre[10];
238526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                sprintf(genre, "%d", genrecode);
238672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
238772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(metadataKey, genre);
238826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            } else if (flags == 1) {
238926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // custom genre string
239026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                buffer[size] = '\0';
239126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
239226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(
239326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                        metadataKey, (const char *)buffer + 8);
239472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
239572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else {
239672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            buffer[size] = '\0';
239772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
239872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(
239972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    metadataKey, (const char *)buffer + 8);
240072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
240172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
240272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
240372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    delete[] buffer;
240472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    buffer = NULL;
240572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
240672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return OK;
240772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
240872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
2409fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhéstatus_t MPEG4Extractor::parse3GPPMetaData(off64_t offset, size_t size, int depth) {
2410d89104a3d5a16298742110bff1d10b43d16fef7bJoshua J. Drake    if (size < 4 || size == SIZE_MAX) {
2411fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        return ERROR_MALFORMED;
2412fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2413fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2414d89104a3d5a16298742110bff1d10b43d16fef7bJoshua J. Drake    uint8_t *buffer = new (std::nothrow) uint8_t[size + 1];
24158da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    if (buffer == NULL) {
24168da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        return ERROR_MALFORMED;
24178da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    }
2418fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    if (mDataSource->readAt(
2419fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                offset, buffer, size) != (ssize_t)size) {
2420fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        delete[] buffer;
2421fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        buffer = NULL;
2422fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2423fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        return ERROR_IO;
2424fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2425fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2426fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    uint32_t metadataKey = 0;
2427fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    switch (mPath[depth]) {
2428fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('t', 'i', 't', 'l'):
2429fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2430fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyTitle;
2431fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2432fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2433fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('p', 'e', 'r', 'f'):
2434fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2435fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyArtist;
2436fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2437fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2438fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'u', 't', 'h'):
2439fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2440fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyWriter;
2441fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2442fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2443fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('g', 'n', 'r', 'e'):
2444fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2445fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyGenre;
2446fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2447fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2448fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'l', 'b', 'm'):
2449fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2450fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (buffer[size - 1] != '\0') {
2451fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé              char tmp[4];
2452fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé              sprintf(tmp, "%u", buffer[size - 1]);
2453fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2454fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé              mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
2455fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2456fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2457fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyAlbum;
2458fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2459fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2460fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('y', 'r', 'r', 'c'):
2461fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2462fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            char tmp[5];
2463fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            uint16_t year = U16_AT(&buffer[4]);
2464fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2465fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (year < 10000) {
2466fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                sprintf(tmp, "%u", year);
2467fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2468fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                mFileMetaData->setCString(kKeyYear, tmp);
2469fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2470fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2471fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2472fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2473fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        default:
2474fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2475fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2476fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2477fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    if (metadataKey > 0) {
2478fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        bool isUTF8 = true; // Common case
2479fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        char16_t *framedata = NULL;
2480fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        int len16 = 0; // Number of UTF-16 characters
2481fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2482fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        // smallest possible valid UTF-16 string w BOM: 0xfe 0xff 0x00 0x00
24834d8ed149894eff1e21195a29d939f2ec389fe5d7Joshua J. Drake        if (size < 6) {
24844d8ed149894eff1e21195a29d939f2ec389fe5d7Joshua J. Drake            return ERROR_MALFORMED;
24854d8ed149894eff1e21195a29d939f2ec389fe5d7Joshua J. Drake        }
24864d8ed149894eff1e21195a29d939f2ec389fe5d7Joshua J. Drake
2487fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        if (size - 6 >= 4) {
2488fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            len16 = ((size - 6) / 2) - 1; // don't include 0x0000 terminator
2489fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            framedata = (char16_t *)(buffer + 6);
2490fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (0xfffe == *framedata) {
2491fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                // endianness marker (BOM) doesn't match host endianness
2492fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                for (int i = 0; i < len16; i++) {
2493fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                    framedata[i] = bswap_16(framedata[i]);
2494fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                }
2495fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                // BOM is now swapped to 0xfeff, we will execute next block too
2496fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2497fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2498fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (0xfeff == *framedata) {
2499fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                // Remove the BOM
2500fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                framedata++;
2501fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                len16--;
2502fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                isUTF8 = false;
2503fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2504fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // else normal non-zero-length UTF-8 string
2505fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // we can't handle UTF-16 without BOM as there is no other
2506fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // indication of encoding.
2507fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2508fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2509fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        if (isUTF8) {
2510d89104a3d5a16298742110bff1d10b43d16fef7bJoshua J. Drake            buffer[size] = 0;
2511fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            mFileMetaData->setCString(metadataKey, (const char *)buffer + 6);
2512fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        } else {
2513fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // Convert from UTF-16 string to UTF-8 string.
2514fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            String8 tmpUTF8str(framedata, len16);
2515fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            mFileMetaData->setCString(metadataKey, tmpUTF8str.string());
2516fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2517fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2518fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2519fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    delete[] buffer;
2520fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    buffer = NULL;
2521fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2522fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    return OK;
2523fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé}
2524fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2525328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhévoid MPEG4Extractor::parseID3v2MetaData(off64_t offset) {
2526328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    ID3 id3(mDataSource, true /* ignorev1 */, offset);
2527328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2528328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    if (id3.isValid()) {
2529328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        struct Map {
2530328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            int key;
2531328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            const char *tag1;
2532328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            const char *tag2;
2533328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        };
2534328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        static const Map kMap[] = {
2535328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyAlbum, "TALB", "TAL" },
2536328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyArtist, "TPE1", "TP1" },
2537328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyAlbumArtist, "TPE2", "TP2" },
2538328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyComposer, "TCOM", "TCM" },
2539328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyGenre, "TCON", "TCO" },
2540328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyTitle, "TIT2", "TT2" },
2541328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyYear, "TYE", "TYER" },
2542328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyAuthor, "TXT", "TEXT" },
2543328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyCDTrackNumber, "TRK", "TRCK" },
2544328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyDiscNumber, "TPA", "TPOS" },
2545328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyCompilation, "TCP", "TCMP" },
2546328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        };
2547328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
2548328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2549328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        for (size_t i = 0; i < kNumMapEntries; ++i) {
2550328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            if (!mFileMetaData->hasData(kMap[i].key)) {
2551328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                ID3::Iterator *it = new ID3::Iterator(id3, kMap[i].tag1);
2552328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                if (it->done()) {
2553328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    delete it;
2554328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    it = new ID3::Iterator(id3, kMap[i].tag2);
2555328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                }
2556328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2557328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                if (it->done()) {
2558328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    delete it;
2559328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    continue;
2560328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                }
2561328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2562328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                String8 s;
2563328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                it->getString(&s);
2564328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                delete it;
2565328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2566328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                mFileMetaData->setCString(kMap[i].key, s);
2567328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            }
2568328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        }
2569328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2570328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        size_t dataSize;
2571328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        String8 mime;
2572328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        const void *data = id3.getAlbumArt(&dataSize, &mime);
2573328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2574328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        if (data) {
2575328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            mFileMetaData->setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize);
2576328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            mFileMetaData->setCString(kKeyAlbumArtMIME, mime.string());
2577328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        }
2578328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    }
2579328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé}
2580328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2581693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
258220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
258320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
2584693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return NULL;
258520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
258620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
258720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
258820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
258920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
2590693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber            return NULL;
259120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
259220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
259320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
259420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
259520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
259620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2597371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
2598371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
2599371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
2600371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
2601c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
2602c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    Trex *trex = NULL;
2603c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    int32_t trackId;
2604c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    if (track->meta->findInt32(kKeyTrackID, &trackId)) {
2605c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        for (size_t i = 0; i < mTrex.size(); i++) {
2606c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            Trex *t = &mTrex.editItemAt(index);
2607c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            if (t->track_ID == (uint32_t) trackId) {
2608c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                trex = t;
2609c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen                break;
2610c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            }
2611c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        }
2612c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    }
2613c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
2614a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("getTrack called, pssh: %zu", mPssh.size());
2615ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2616942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    return new MPEG4Source(this,
261705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            track->meta, mDataSource, track->timescale, track->sampleTable,
2618c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen            mSidxEntries, trex, mMoofOffset);
261920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
262020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2621bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber// static
2622bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) {
2623bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const char *mime;
2624bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    CHECK(track->meta->findCString(kKeyMIMEType, &mime));
2625bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2626bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    uint32_t type;
2627bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const void *data;
2628bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    size_t size;
2629bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
2630bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyAVCC, &type, &data, &size)
2631bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeAVCC) {
2632bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
2633bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
26343b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
26353b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        if (!track->meta->findData(kKeyHVCC, &type, &data, &size)
26363b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar                    || type != kTypeHVCC) {
26373b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar            return ERROR_MALFORMED;
26383b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        }
2639bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
2640bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
2641bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyESDS, &type, &data, &size)
2642bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeESDS) {
2643bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
2644bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
2645bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    }
2646bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2647ce171998009e1abcb0c718c0aee495fcd33645e2Robert Shih    if (track->sampleTable == NULL || !track->sampleTable->isValid()) {
2648169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        // Make sure we have all the metadata we need.
2649ce171998009e1abcb0c718c0aee495fcd33645e2Robert Shih        ALOGE("stbl atom missing/invalid.");
2650169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        return ERROR_MALFORMED;
2651169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber    }
2652169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber
2653bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    return OK;
2654bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber}
2655bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2656f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivitypedef enum {
2657f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_NONE             = -1,
2658f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_NULL_OBJECT      = 0,
2659f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_MAIN         = 1, /**< Main profile                              */
2660f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_AAC_LC           = 2,   /**< Low Complexity object                     */
2661f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_SSR          = 3,
2662f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_LTP          = 4,
2663f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_SBR              = 5,
2664f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_SCAL         = 6,
2665f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_TWIN_VQ          = 7,
2666f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_CELP             = 8,
2667f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_HVXC             = 9,
2668f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_10          = 10, /**< (reserved)                                */
2669f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_11          = 11, /**< (reserved)                                */
2670f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_TTSI             = 12, /**< TTSI Object                               */
2671f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MAIN_SYNTH       = 13, /**< Main Synthetic object                     */
2672f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_WAV_TAB_SYNTH    = 14, /**< Wavetable Synthesis object                */
2673f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_GEN_MIDI         = 15, /**< General MIDI object                       */
2674f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ALG_SYNTH_AUD_FX = 16, /**< Algorithmic Synthesis and Audio FX object */
2675f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_AAC_LC        = 17,   /**< Error Resilient(ER) AAC Low Complexity    */
2676f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_18          = 18, /**< (reserved)                                */
2677f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_AAC_LTP       = 19, /**< Error Resilient(ER) AAC LTP object        */
2678f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_AAC_SCAL      = 20,   /**< Error Resilient(ER) AAC Scalable object   */
2679f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_TWIN_VQ       = 21, /**< Error Resilient(ER) TwinVQ object         */
2680f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_BSAC          = 22,   /**< Error Resilient(ER) BSAC object           */
2681f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_AAC_LD        = 23,   /**< Error Resilient(ER) AAC LowDelay object   */
2682f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_CELP          = 24, /**< Error Resilient(ER) CELP object           */
2683f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_HVXC          = 25, /**< Error Resilient(ER) HVXC object           */
2684f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_HILN          = 26, /**< Error Resilient(ER) HILN object           */
2685f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_PARA          = 27, /**< Error Resilient(ER) Parametric object     */
2686f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_28          = 28, /**< might become SSC                          */
2687f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_PS               = 29,   /**< PS, Parametric Stereo (includes SBR)      */
2688f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MPEGS            = 30, /**< MPEG Surround                             */
2689f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2690f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ESCAPE           = 31,   /**< Signal AOT uses more than 5 bits          */
2691f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2692f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MP3ONMP4_L1      = 32, /**< MPEG-Layer1 in mp4                        */
2693f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MP3ONMP4_L2      = 33, /**< MPEG-Layer2 in mp4                        */
2694f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MP3ONMP4_L3      = 34, /**< MPEG-Layer3 in mp4                        */
2695f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_35          = 35, /**< might become DST                          */
2696f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_36          = 36, /**< might become ALS                          */
2697f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_SLS          = 37, /**< AAC + SLS                                 */
2698f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_SLS              = 38, /**< SLS                                       */
2699f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_AAC_ELD       = 39, /**< AAC Enhanced Low Delay                    */
2700f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2701f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_USAC             = 42, /**< USAC                                      */
2702f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_SAOC             = 43, /**< SAOC                                      */
2703f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_LD_MPEGS         = 44, /**< Low Delay MPEG Surround                   */
2704f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2705f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD50           = 50,  /**< Interim AOT for Rsvd50                   */
2706f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi} AUDIO_OBJECT_TYPE;
2707f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2708ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
2709ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        const void *esds_data, size_t esds_size) {
2710ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    ESDS esds(esds_data, esds_size);
271181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
271281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    uint8_t objectTypeIndication;
271381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
271481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return ERROR_MALFORMED;
271581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
271681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
271781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (objectTypeIndication == 0xe1) {
271881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        // This isn't MPEG4 audio at all, it's QCELP 14k...
271981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
272081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return OK;
272181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
272281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
2723633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong    if (objectTypeIndication  == 0x6b) {
2724633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // The media subtype is MP3 audio
2725633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // Our software MP3 audio decoder may not be able to handle
2726633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // packetized MP3 audio; for now, lets just return ERROR_UNSUPPORTED
272729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("MP3 track in MP4/3GPP file is not supported");
2728633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        return ERROR_UNSUPPORTED;
2729633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong    }
2730633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong
2731ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    const uint8_t *csd;
2732ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    size_t csd_size;
2733ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (esds.getCodecSpecificInfo(
2734ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                (const void **)&csd, &csd_size) != OK) {
2735ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
2736ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2737ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2738ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#if 0
2739ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    printf("ESD of size %d\n", csd_size);
2740ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    hexdump(csd, csd_size);
2741ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#endif
2742ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2743a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    if (csd_size == 0) {
2744a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // There's no further information, i.e. no codec specific data
2745a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // Let's assume that the information provided in the mpeg4 headers
2746a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // is accurate and hope for the best.
2747a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
2748a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        return OK;
2749a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    }
2750a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
2751ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (csd_size < 2) {
2752ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
2753ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2754ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
275500307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent    static uint32_t kSamplingRate[] = {
275600307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
275700307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        16000, 12000, 11025, 8000, 7350
275800307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent    };
275900307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent
2760aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    ABitReader br(csd, csd_size);
2761aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    uint32_t objectType = br.getBits(5);
2762ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2763aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    if (objectType == 31) {  // AAC-ELD => additional 6 bits
2764aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        objectType = 32 + br.getBits(6);
2765ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2766ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2767db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent    //keep AOT type
2768db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent    mLastTrack->meta->setInt32(kKeyAACAOT, objectType);
2769db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent
2770aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    uint32_t freqIndex = br.getBits(4);
2771aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
2772ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t sampleRate = 0;
2773ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t numChannels = 0;
2774ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (freqIndex == 15) {
2775ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        if (csd_size < 5) {
2776ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            return ERROR_MALFORMED;
2777ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
2778aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        sampleRate = br.getBits(24);
2779aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        numChannels = br.getBits(4);
2780ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    } else {
2781595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen        numChannels = br.getBits(4);
278200307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent
278300307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        if (freqIndex == 13 || freqIndex == 14) {
278400307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            return ERROR_MALFORMED;
2785ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
2786ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
278700307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        sampleRate = kSamplingRate[freqIndex];
278800307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent    }
2789595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen
2790f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    if (objectType == AOT_SBR || objectType == AOT_PS) {//SBR specific config per 14496-3 table 1.13
279100307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        uint32_t extFreqIndex = br.getBits(4);
279200307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        int32_t extSampleRate;
279300307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        if (extFreqIndex == 15) {
279400307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            if (csd_size < 8) {
2795595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen                return ERROR_MALFORMED;
2796595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen            }
279700307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            extSampleRate = br.getBits(24);
279800307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        } else {
279900307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            if (extFreqIndex == 13 || extFreqIndex == 14) {
280000307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent                return ERROR_MALFORMED;
280100307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            }
280200307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            extSampleRate = kSamplingRate[extFreqIndex];
2803595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen        }
280400307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        //TODO: save the extension sampling rate value in meta data =>
280500307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        //      mLastTrack->meta->setInt32(kKeyExtSampleRate, extSampleRate);
2806ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2807ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2808f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    switch (numChannels) {
2809f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        // values defined in 14496-3_2009 amendment-4 Table 1.19 - Channel Configuration
2810f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 0:
2811f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 1:// FC
2812f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 2:// FL FR
2813f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 3:// FC, FL FR
2814f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 4:// FC, FL FR, RC
2815f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 5:// FC, FL FR, SL SR
2816f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 6:// FC, FL FR, SL SR, LFE
2817f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            //numChannels already contains the right value
2818f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            break;
2819f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 11:// FC, FL FR, SL SR, RC, LFE
2820f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            numChannels = 7;
2821f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            break;
2822f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 7: // FC, FCL FCR, FL FR, SL SR, LFE
2823f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 12:// FC, FL  FR,  SL SR, RL RR, LFE
2824f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 14:// FC, FL  FR,  SL SR, LFE, FHL FHR
2825f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            numChannels = 8;
2826f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            break;
2827f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        default:
2828f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            return ERROR_UNSUPPORTED;
2829f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    }
2830f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2831f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    {
2832f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        if (objectType == AOT_SBR || objectType == AOT_PS) {
2833f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            objectType = br.getBits(5);
2834f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2835f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            if (objectType == AOT_ESCAPE) {
2836f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                objectType = 32 + br.getBits(6);
2837f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            }
2838f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        }
2839f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        if (objectType == AOT_AAC_LC || objectType == AOT_ER_AAC_LC ||
2840f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                objectType == AOT_ER_AAC_LD || objectType == AOT_ER_AAC_SCAL ||
2841f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                objectType == AOT_ER_BSAC) {
2842f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            const int32_t frameLengthFlag = br.getBits(1);
2843f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2844f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            const int32_t dependsOnCoreCoder = br.getBits(1);
2845f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2846f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            if (dependsOnCoreCoder ) {
2847f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t coreCoderDelay = br.getBits(14);
2848f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            }
2849f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
285045452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            int32_t extensionFlag = -1;
285145452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            if (br.numBitsLeft() > 0) {
285245452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                extensionFlag = br.getBits(1);
285345452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            } else {
285445452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                switch (objectType) {
285545452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                // 14496-3 4.5.1.1 extensionFlag
285645452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_AAC_LC:
285745452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    extensionFlag = 0;
285845452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    break;
285945452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_ER_AAC_LC:
286045452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_ER_AAC_SCAL:
286145452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_ER_BSAC:
286245452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                case AOT_ER_AAC_LD:
286345452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    extensionFlag = 1;
286445452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    break;
286545452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                default:
286645452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    TRESPASS();
286745452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                    break;
286845452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                }
286945452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                ALOGW("csd missing extension flag; assuming %d for object type %u.",
287045452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih                        extensionFlag, objectType);
287145452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            }
2872f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
287345452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih            if (numChannels == 0) {
2874f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                int32_t channelsEffectiveNum = 0;
2875f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                int32_t channelsNum = 0;
2876f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t ElementInstanceTag = br.getBits(4);
2877f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t Profile = br.getBits(2);
2878f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t SamplingFrequencyIndex = br.getBits(4);
2879f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumFrontChannelElements = br.getBits(4);
2880f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumSideChannelElements = br.getBits(4);
2881f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumBackChannelElements = br.getBits(4);
2882f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumLfeChannelElements = br.getBits(2);
2883f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumAssocDataElements = br.getBits(3);
2884f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumValidCcElements = br.getBits(4);
2885f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2886f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t MonoMixdownPresent = br.getBits(1);
2887f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                if (MonoMixdownPresent != 0) {
2888f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t MonoMixdownElementNumber = br.getBits(4);
2889f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2890f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2891f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t StereoMixdownPresent = br.getBits(1);
2892f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                if (StereoMixdownPresent != 0) {
2893f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t StereoMixdownElementNumber = br.getBits(4);
2894f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2895f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2896f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t MatrixMixdownIndexPresent = br.getBits(1);
2897f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                if (MatrixMixdownIndexPresent != 0) {
2898f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t MatrixMixdownIndex = br.getBits(2);
2899f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t PseudoSurroundEnable = br.getBits(1);
2900f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2901f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2902f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                int i;
2903f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumFrontChannelElements; i++) {
2904f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t FrontElementIsCpe = br.getBits(1);
2905f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t FrontElementTagSelect = br.getBits(4);
2906f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += FrontElementIsCpe ? 2 : 1;
2907f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2908f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2909f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumSideChannelElements; i++) {
2910f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t SideElementIsCpe = br.getBits(1);
2911f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t SideElementTagSelect = br.getBits(4);
2912f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += SideElementIsCpe ? 2 : 1;
2913f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2914f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2915f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumBackChannelElements; i++) {
2916f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t BackElementIsCpe = br.getBits(1);
2917f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t BackElementTagSelect = br.getBits(4);
2918f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += BackElementIsCpe ? 2 : 1;
2919f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2920f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                channelsEffectiveNum = channelsNum;
2921f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2922f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumLfeChannelElements; i++) {
2923f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t LfeElementTagSelect = br.getBits(4);
2924f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += 1;
2925f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2926f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                ALOGV("mpeg4 audio channelsNum = %d", channelsNum);
2927f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                ALOGV("mpeg4 audio channelsEffectiveNum = %d", channelsEffectiveNum);
2928f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                numChannels = channelsNum;
2929f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            }
2930f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        }
2931f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    }
2932f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2933ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (numChannels == 0) {
2934ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_UNSUPPORTED;
2935ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2936ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2937ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevSampleRate;
2938ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
2939ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2940ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevSampleRate != sampleRate) {
29413856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("mpeg4 audio sample rate different from previous setting. "
2942ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevSampleRate, sampleRate);
2943ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2944ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2945ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
2946ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2947ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevChannelCount;
2948ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
2949ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2950ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevChannelCount != numChannels) {
29513856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("mpeg4 audio channel count different from previous setting. "
2952ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevChannelCount, numChannels);
2953ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2954ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2955ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
2956ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2957ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    return OK;
2958ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber}
2959ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
296020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
296120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
296220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::MPEG4Source(
2963942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen        const sp<MPEG4Extractor> &owner,
296420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        const sp<MetaData> &format,
2965693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &dataSource,
296648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        int32_t timeScale,
296705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const sp<SampleTable> &sampleTable,
296805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        Vector<SidxEntry> &sidx,
2969c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        const Trex *trex,
297005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t firstMoofOffset)
2971942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen    : mOwner(owner),
2972942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen      mFormat(format),
297320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDataSource(dataSource),
297448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber      mTimescale(timeScale),
297520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSampleTable(sampleTable),
297620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCurrentSampleIndex(0),
297705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentFragmentIndex(0),
297805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mSegments(sidx),
2979c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen      mTrex(trex),
298005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mFirstMoofOffset(firstMoofOffset),
298105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentMoofOffset(firstMoofOffset),
298205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentTime(0),
2983ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoAllocSize(0),
2984ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoSizes(NULL),
2985ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoOffsetsAllocSize(0),
2986ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoOffsets(NULL),
298720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mIsAVC(false),
29883b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar      mIsHEVC(false),
29896064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber      mNALLengthSize(0),
299020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mStarted(false),
299120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mGroup(NULL),
299220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mBuffer(NULL),
2993dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber      mWantsNALFragments(false),
29940024245e134467d120b40099da16c467dc365e76Andreas Huber      mSrcBuffer(NULL) {
2995ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2996c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    memset(&mTrackFragmentHeaderInfo, 0, sizeof(mTrackFragmentHeaderInfo));
2997c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen
2998ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mFormat->findInt32(kKeyCryptoMode, &mCryptoMode);
299948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    mDefaultIVSize = 0;
3000ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mFormat->findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize);
3001ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t keytype;
3002ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    const void *key;
3003ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    size_t keysize;
3004ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mFormat->findData(kKeyCryptoKey, &keytype, &key, &keysize)) {
3005ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        CHECK(keysize <= 16);
3006ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memset(mCryptoKey, 0, 16);
3007ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memcpy(mCryptoKey, key, keysize);
3008ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3009ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
301020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
301120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mFormat->findCString(kKeyMIMEType, &mime);
3012dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(success);
301320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
301418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber    mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
30153b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    mIsHEVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC);
30166064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
30176064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    if (mIsAVC) {
30186064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        uint32_t type;
30196064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const void *data;
30206064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t size;
30216064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(format->findData(kKeyAVCC, &type, &data, &size));
30226064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
30236064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const uint8_t *ptr = (const uint8_t *)data;
30246064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
30256064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(size >= 7);
3026ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
30276064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
30286064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        // The number of bytes used to encode the length of a NAL unit.
30296064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        mNALLengthSize = 1 + (ptr[4] & 3);
30303b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    } else if (mIsHEVC) {
30313b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        uint32_t type;
30323b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        const void *data;
30333b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        size_t size;
30343b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        CHECK(format->findData(kKeyHVCC, &type, &data, &size));
30353b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
30363b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        const uint8_t *ptr = (const uint8_t *)data;
30373b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
30383b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        CHECK(size >= 7);
30393b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
30403b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar
30413b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        mNALLengthSize = 1 + (ptr[14 + 7] & 3);
30426064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
304305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
304405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    CHECK(format->findInt32(kKeyTrackID, &mTrackId));
304505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
304605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mFirstMoofOffset != 0) {
304705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t offset = mFirstMoofOffset;
304805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        parseChunk(&offset);
304905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
305020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
305120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
305220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::~MPEG4Source() {
305320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mStarted) {
305420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        stop();
305520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
3056ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    free(mCurrentSampleInfoSizes);
3057ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    free(mCurrentSampleInfoOffsets);
305820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
305920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
306020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::start(MetaData *params) {
30617b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
30627b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
3063dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(!mStarted);
306420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
306520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t val;
3066dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (params && params->findInt32(kKeyWantsNALFragments, &val)
306720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        && val != 0) {
3068dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = true;
306920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    } else {
3070dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = false;
307120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
307220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
307320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = new MediaBufferGroup;
307420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3075738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    int32_t max_size;
3076738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
307720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3078738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    mGroup->add_buffer(new MediaBuffer(max_size));
30790024245e134467d120b40099da16c467dc365e76Andreas Huber
30808da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    mSrcBuffer = new (std::nothrow) uint8_t[max_size];
30818da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    if (mSrcBuffer == NULL) {
30828da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        // file probably specified a bad max size
30838da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen        return ERROR_MALFORMED;
30848da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen    }
308520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
308620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = true;
308720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
308820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
308920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
309020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
309120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::stop() {
30927b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
30937b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
3094dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
309520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
309620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mBuffer != NULL) {
309720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->release();
309820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
309920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
310020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31010024245e134467d120b40099da16c467dc365e76Andreas Huber    delete[] mSrcBuffer;
31020024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = NULL;
31030024245e134467d120b40099da16c467dc365e76Andreas Huber
310420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    delete mGroup;
310520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = NULL;
310620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
310720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = false;
310820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mCurrentSampleIndex = 0;
310920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
311020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
311120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
311220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
311305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseChunk(off64_t *offset) {
311405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t hdr[2];
311505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
311605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_IO;
311705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
311805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t chunk_size = ntohl(hdr[0]);
311905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t chunk_type = ntohl(hdr[1]);
312005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t data_offset = *offset + 8;
312105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
312205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (chunk_size == 1) {
312305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
312405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_IO;
312505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
312605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        chunk_size = ntoh64(chunk_size);
312705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        data_offset += 8;
312805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
312905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (chunk_size < 16) {
313005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            // The smallest valid chunk is 16 bytes long in this case.
313105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
313205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
313305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (chunk_size < 8) {
313405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // The smallest valid chunk is 8 bytes long.
313505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
313605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
313705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
313805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    char chunk[5];
313905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    MakeFourCCString(chunk_type, chunk);
314005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Source chunk %s @ %llx", chunk, *offset);
314105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
314205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t chunk_data_size = *offset + chunk_size - data_offset;
314305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
314405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    switch(chunk_type) {
314505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
314605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'r', 'a', 'f'):
314705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('m', 'o', 'o', 'f'): {
314805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t stop_offset = *offset + chunk_size;
314905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset = data_offset;
315005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            while (*offset < stop_offset) {
315105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err = parseChunk(offset);
315205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (err != OK) {
315305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return err;
315405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
315505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
315605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
31573f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                // *offset points to the box following this moof. Find the next moof from there.
31583f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen
31593f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                while (true) {
31603f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
31613f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                        return ERROR_END_OF_STREAM;
31623f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    }
31633f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    chunk_size = ntohl(hdr[0]);
31643f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    chunk_type = ntohl(hdr[1]);
31653f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
31663f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                        mNextMoofOffset = *offset;
31673f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                        break;
31683f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    }
31693f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    *offset += chunk_size;
31703f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                }
317105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
317205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
317305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
317405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
317505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'f', 'h', 'd'): {
317605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err;
317705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if ((err = parseTrackFragmentHeader(data_offset, chunk_data_size)) != OK) {
317805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return err;
317905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
318005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                *offset += chunk_size;
318105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                break;
318205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
318305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
318405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'r', 'u', 'n'): {
318505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err;
318605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (mLastParsedTrackId == mTrackId) {
318705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    if ((err = parseTrackFragmentRun(data_offset, chunk_data_size)) != OK) {
318805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        return err;
318905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    }
319005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
319105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
319205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                *offset += chunk_size;
319305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                break;
319405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
319505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3196ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'a', 'i', 'z'): {
3197ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            status_t err;
3198ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((err = parseSampleAuxiliaryInformationSizes(data_offset, chunk_data_size)) != OK) {
3199ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return err;
3200ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3201ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
3202ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
3203ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3204ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'a', 'i', 'o'): {
3205ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            status_t err;
3206ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((err = parseSampleAuxiliaryInformationOffsets(data_offset, chunk_data_size)) != OK) {
3207ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return err;
3208ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3209ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
3210ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
3211ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3212ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3213ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('m', 'd', 'a', 't'): {
3214ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // parse DRM info if present
3215ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("MPEG4Source::parseChunk mdat");
3216ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // if saiz/saoi was previously observed, do something with the sampleinfos
3217ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
3218ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
3219ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3220ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
322105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        default: {
322205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset += chunk_size;
322305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
322405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
322505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
322605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
322705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
322805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
322984333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG4Source::parseSampleAuxiliaryInformationSizes(
323084333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        off64_t offset, off64_t /* size */) {
3231ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("parseSampleAuxiliaryInformationSizes");
3232ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // 14496-12 8.7.12
3233ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t version;
3234ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(
3235ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset, &version, sizeof(version))
3236ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            < (ssize_t)sizeof(version)) {
3237ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3238ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3239ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3240ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (version != 0) {
3241ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_UNSUPPORTED;
3242ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3243ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
3244ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3245ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t flags;
3246ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt24(offset, &flags)) {
3247ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3248ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3249ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 3;
3250ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3251ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (flags & 1) {
3252ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        uint32_t tmp;
3253ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
3254ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_MALFORMED;
3255ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3256ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentAuxInfoType = tmp;
3257ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        offset += 4;
3258ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
3259ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_MALFORMED;
3260ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3261ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentAuxInfoTypeParameter = tmp;
3262ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        offset += 4;
3263ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3264ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3265ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t defsize;
3266ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(offset, &defsize, 1) != 1) {
3267ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_MALFORMED;
3268ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3269ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mCurrentDefaultSampleInfoSize = defsize;
3270ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
3271ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3272ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t smplcnt;
3273ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &smplcnt)) {
3274ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_MALFORMED;
3275ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
327648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    mCurrentSampleInfoCount = smplcnt;
3277ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 4;
3278ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
327948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (mCurrentDefaultSampleInfoSize != 0) {
328048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        ALOGV("@@@@ using default sample info size of %d", mCurrentDefaultSampleInfoSize);
328148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return OK;
328248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
3283ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (smplcnt > mCurrentSampleInfoAllocSize) {
3284ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoSizes = (uint8_t*) realloc(mCurrentSampleInfoSizes, smplcnt);
3285ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoAllocSize = smplcnt;
3286ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3287ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3288ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mDataSource->readAt(offset, mCurrentSampleInfoSizes, smplcnt);
3289ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    return OK;
3290ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen}
3291ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
329284333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(
329384333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        off64_t offset, off64_t /* size */) {
3294ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("parseSampleAuxiliaryInformationOffsets");
3295ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // 14496-12 8.7.13
3296ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t version;
3297ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(offset, &version, sizeof(version)) != 1) {
3298ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3299ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3300ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
3301ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3302ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t flags;
3303ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt24(offset, &flags)) {
3304ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3305ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3306ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 3;
3307ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3308ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t entrycount;
3309ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &entrycount)) {
3310ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3311ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3312ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 4;
3313ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3314ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (entrycount > mCurrentSampleInfoOffsetsAllocSize) {
3315ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoOffsets = (uint64_t*) realloc(mCurrentSampleInfoOffsets, entrycount * 8);
3316ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoOffsetsAllocSize = entrycount;
3317ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3318ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mCurrentSampleInfoOffsetCount = entrycount;
3319ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3320ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < entrycount; i++) {
3321ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (version == 0) {
3322ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t tmp;
3323ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (!mDataSource->getUInt32(offset, &tmp)) {
3324ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
3325ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3326ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mCurrentSampleInfoOffsets[i] = tmp;
3327ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset += 4;
3328ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        } else {
3329ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint64_t tmp;
3330ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (!mDataSource->getUInt64(offset, &tmp)) {
3331ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
3332ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3333ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mCurrentSampleInfoOffsets[i] = tmp;
3334ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset += 8;
3335ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3336ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3337ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3338ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // parse clear/encrypted data
3339ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3340ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    off64_t drmoffset = mCurrentSampleInfoOffsets[0]; // from moof
3341ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3342ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    drmoffset += mCurrentMoofOffset;
3343ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int ivlength;
3344ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    CHECK(mFormat->findInt32(kKeyCryptoDefaultIVSize, &ivlength));
334548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
334648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    // read CencSampleAuxiliaryDataFormats
3347ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mCurrentSampleInfoCount; i++) {
3348ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Sample *smpl = &mCurrentSamples.editItemAt(i);
3349ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3350ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memset(smpl->iv, 0, 16);
3351ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (mDataSource->readAt(drmoffset, smpl->iv, ivlength) != ivlength) {
3352ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_IO;
3353ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3354ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3355ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        drmoffset += ivlength;
3356ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
335748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        int32_t smplinfosize = mCurrentDefaultSampleInfoSize;
335848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        if (smplinfosize == 0) {
335948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smplinfosize = mCurrentSampleInfoSizes[i];
3360ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
336148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        if (smplinfosize > ivlength) {
336248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint16_t numsubsamples;
336348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (!mDataSource->getUInt16(drmoffset, &numsubsamples)) {
3364ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
3365ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3366ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            drmoffset += 2;
336748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            for (size_t j = 0; j < numsubsamples; j++) {
336848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                uint16_t numclear;
336948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                uint32_t numencrypted;
337048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                if (!mDataSource->getUInt16(drmoffset, &numclear)) {
337148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                    return ERROR_IO;
337248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                }
337348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                drmoffset += 2;
337448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                if (!mDataSource->getUInt32(drmoffset, &numencrypted)) {
337548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                    return ERROR_IO;
337648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                }
337748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                drmoffset += 4;
337848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->clearsizes.add(numclear);
337948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->encryptedsizes.add(numencrypted);
3380ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
338148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        } else {
338248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smpl->clearsizes.add(0);
338348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smpl->encryptedsizes.add(smpl->size);
3384ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3385ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3386ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3387ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3388ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    return OK;
3389ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen}
3390ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
339105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentHeader(off64_t offset, off64_t size) {
339205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
339305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 8) {
339405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
339505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
339605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
339705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
3398ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags
339905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
340005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
340105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
340205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & 0xff000000) {
340305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
340405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
340505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
340605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, (uint32_t*)&mLastParsedTrackId)) {
340705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
340805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
340905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
341005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mLastParsedTrackId != mTrackId) {
341105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // this is not the right track, skip it
341205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
341305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
341405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
341505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mFlags = flags;
341605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mTrackID = mLastParsedTrackId;
341705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 8;
341805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 8;
341905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
342005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("fragment header: %08x %08x", flags, mTrackFragmentHeaderInfo.mTrackID);
342105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
342205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent) {
342305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 8) {
342405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
342505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
342605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
342705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset, &mTrackFragmentHeaderInfo.mBaseDataOffset)) {
342805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
342905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
343005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 8;
343105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 8;
343205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
343305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
343405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent) {
343505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
343605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
343705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
343805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
343905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mSampleDescriptionIndex)) {
344005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
344105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
344205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
344305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
344405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
344505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
344605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
344705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
344805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
344905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
345005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
345105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleDuration)) {
345205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
345305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
345405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
345505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
345605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
345705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
345805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
345905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
346005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
346105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
346205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
346305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleSize)) {
346405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
346505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
346605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
346705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
346805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
346905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
347005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
347105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
347205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
347305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
347405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
347505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleFlags)) {
347605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
347705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
347805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
347905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
348005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
348105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
348205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!(flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent)) {
348305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mTrackFragmentHeaderInfo.mBaseDataOffset = mCurrentMoofOffset;
348405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
348505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
348605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mDataOffset = 0;
348705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
348805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
348905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
349005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentRun(off64_t offset, off64_t size) {
349105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
349205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Extractor::parseTrackFragmentRun");
349305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 8) {
349405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
349505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
349605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
349705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    enum {
349805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kDataOffsetPresent                  = 0x01,
349905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kFirstSampleFlagsPresent            = 0x04,
350005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleDurationPresent              = 0x100,
350105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleSizePresent                  = 0x200,
350205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleFlagsPresent                 = 0x400,
350305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleCompositionTimeOffsetPresent = 0x800,
350405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
350505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
350605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
350705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) {
350805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
350905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
351005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("fragment run flags: %08x", flags);
351105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
351205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & 0xff000000) {
351305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
351405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
351505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
351605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if ((flags & kFirstSampleFlagsPresent) && (flags & kSampleFlagsPresent)) {
351705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // These two shall not be used together.
351805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
351905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
352005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
352105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t sampleCount;
352205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, &sampleCount)) {
352305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
352405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
352505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 8;
352605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 8;
352705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
352805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t dataOffset = mTrackFragmentHeaderInfo.mDataOffset;
352905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
353005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t firstSampleFlags = 0;
353105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
353205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kDataOffsetPresent) {
353305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
353405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
353505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
353605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
353705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int32_t dataOffsetDelta;
353805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, (uint32_t*)&dataOffsetDelta)) {
353905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
354005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
354105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
354205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        dataOffset = mTrackFragmentHeaderInfo.mBaseDataOffset + dataOffsetDelta;
354305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
354405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
354505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
354605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
354705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
354805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kFirstSampleFlagsPresent) {
354905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
355005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
355105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
355205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
355305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &firstSampleFlags)) {
355405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
355505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
355605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
355705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
355805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
355905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
356005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t sampleDuration = 0, sampleSize = 0, sampleFlags = 0,
356105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen             sampleCtsOffset = 0;
356205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
356305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size_t bytesPerSample = 0;
356405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleDurationPresent) {
356505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
356605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
356705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
356805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration;
3569c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen    } else if (mTrex) {
3570c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        sampleDuration = mTrex->default_sample_duration;
357105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
357205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
357305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleSizePresent) {
357405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
357505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
357605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
357705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
357805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
357905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
358005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
358105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
358205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleFlagsPresent) {
358305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
358405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
358505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
358605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
358705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
358805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
358905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
359005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
359105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleCompositionTimeOffsetPresent) {
359205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
359305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
359405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleCtsOffset = 0;
359505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
359605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3597a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    if (size < (off64_t)sampleCount * bytesPerSample) {
359805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
359905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
360005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
360105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Sample tmp;
360205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    for (uint32_t i = 0; i < sampleCount; ++i) {
360305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleDurationPresent) {
360405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleDuration)) {
360505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
360605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
360705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
360805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
360905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
361005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleSizePresent) {
361105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleSize)) {
361205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
361305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
361405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
361505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
361605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
361705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleFlagsPresent) {
361805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleFlags)) {
361905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
362005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
362105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
362205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
362305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
362405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleCompositionTimeOffsetPresent) {
362505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleCtsOffset)) {
362605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
362705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
362805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
362905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
363005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3631a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("adding sample %d at offset 0x%08" PRIx64 ", size %u, duration %u, "
3632ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen              " flags 0x%08x", i + 1,
363305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dataOffset, sampleSize, sampleDuration,
363405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                (flags & kFirstSampleFlagsPresent) && i == 0
363505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ? firstSampleFlags : sampleFlags);
363605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.offset = dataOffset;
363705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.size = sampleSize;
363805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.duration = sampleDuration;
3639c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        tmp.compositionOffset = sampleCtsOffset;
364005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentSamples.add(tmp);
364105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
364205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        dataOffset += sampleSize;
364305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
364405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
364505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mDataOffset = dataOffset;
364605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
364705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
364805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
364905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
365020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> MPEG4Source::getFormat() {
36517b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
36527b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
365320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return mFormat;
365420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
365520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36566064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const {
36576064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    switch (mNALLengthSize) {
36586064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 1:
36596064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return *data;
36606064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 2:
36616064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U16_AT(data);
36626064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 3:
36636064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return ((size_t)data[0] << 16) | U16_AT(&data[1]);
36646064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 4:
36656064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U32_AT(data);
36666064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
36676064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
36686064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // This cannot happen, mNALLengthSize springs to life by adding 1 to
36696064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // a 2-bit integer.
36706064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    CHECK(!"Should not be here.");
36716064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
36726064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    return 0;
36736064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber}
36746064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
367520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::read(
367620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
36777b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
36787b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
3679dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
368020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
368105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mFirstMoofOffset > 0) {
368205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return fragmentedRead(out, options);
368305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
368405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
368520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *out = NULL;
368620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3687abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    int64_t targetSampleTimeUs = -1;
3688abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
368920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t seekTimeUs;
3690abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
3691abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
3692abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t findFlags = 0;
3693abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        switch (mode) {
3694abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_PREVIOUS_SYNC:
3695abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagBefore;
3696abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3697abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_NEXT_SYNC:
3698abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagAfter;
3699abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3700abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST_SYNC:
3701abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST:
3702abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagClosest;
3703abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3704abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            default:
3705abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                CHECK(!"Should not be here.");
3706abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3707abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3708abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
370920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        uint32_t sampleIndex;
3710abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        status_t err = mSampleTable->findSampleAtTime(
3711599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar                seekTimeUs, 1000000, mTimescale,
3712abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                &sampleIndex, findFlags);
3713abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3714abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
3715abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // We found the closest sample already, now we want the sync
3716abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // sample preceding it (or the sample itself of course), even
3717abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // if the subsequent sync sample is closer.
3718abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            findFlags = SampleTable::kFlagBefore;
3719abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3720abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3721abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleIndex;
3722abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (err == OK) {
3723abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            err = mSampleTable->findSyncSampleNear(
3724abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    sampleIndex, &syncSampleIndex, findFlags);
3725abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
372620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3727788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        uint32_t sampleTime;
3728788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        if (err == OK) {
3729788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber            err = mSampleTable->getMetaDataForSample(
3730788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber                    sampleIndex, NULL, NULL, &sampleTime);
3731788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        }
3732788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber
373320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (err != OK) {
37345295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            if (err == ERROR_OUT_OF_RANGE) {
37355295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // An attempt to seek past the end of the stream would
37365295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // normally cause this ERROR_OUT_OF_RANGE error. Propagating
37375295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // this all the way to the MediaPlayer would cause abnormal
37385295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // termination. Legacy behaviour appears to be to behave as if
37395295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // we had seeked to the end of stream, ending normally.
37405295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                err = ERROR_END_OF_STREAM;
37415295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            }
374205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("end of stream");
374320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return err;
374420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
374520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3746abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
3747abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
3748abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3749abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3750abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#if 0
3751abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleTime;
3752abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
3753abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    syncSampleIndex, NULL, NULL, &syncSampleTime));
3754abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3755df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("seek to time %lld us => sample at time %lld us, "
3756abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             "sync sample at time %lld us",
3757abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             seekTimeUs,
3758abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             sampleTime * 1000000ll / mTimescale,
3759abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             syncSampleTime * 1000000ll / mTimescale);
3760abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#endif
3761abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3762abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        mCurrentSampleIndex = syncSampleIndex;
376320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mBuffer != NULL) {
376420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
376520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
376620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
376720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
376820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // fall through
376920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
377020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3771c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset;
37720024245e134467d120b40099da16c467dc365e76Andreas Huber    size_t size;
3773170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih    uint32_t cts, stts;
37748bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    bool isSyncSample;
3775dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool newBuffer = false;
3776dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (mBuffer == NULL) {
3777dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        newBuffer = true;
377820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3779c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        status_t err =
3780c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber            mSampleTable->getMetaDataForSample(
3781170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                    mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample, &stts);
378220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3783dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
3784dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
3785dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3786dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3787dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        err = mGroup->acquire_buffer(&mBuffer);
3788c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
3789dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
3790ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            CHECK(mBuffer == NULL);
3791dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
3792dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
37930024245e134467d120b40099da16c467dc365e76Andreas Huber    }
379420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37953b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    if ((!mIsAVC && !mIsHEVC) || mWantsNALFragments) {
3796dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (newBuffer) {
3797dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ssize_t num_bytes_read =
379834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
3799dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3800dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            if (num_bytes_read < (ssize_t)size) {
3801dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer->release();
3802dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer = NULL;
3803dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3804dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                return ERROR_IO;
3805dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            }
3806dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
38077b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber            CHECK(mBuffer != NULL);
3808dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->set_range(0, size);
3809dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->meta_data()->clear();
381048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mBuffer->meta_data()->setInt64(
38114678a6dc5f09008481524949a9667af5a6190374Andreas Huber                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
3812170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih            mBuffer->meta_data()->setInt64(
3813170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                    kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
3814abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3815abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            if (targetSampleTimeUs >= 0) {
3816abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                mBuffer->meta_data()->setInt64(
3817abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                        kKeyTargetTime, targetSampleTimeUs);
3818abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            }
3819abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
38208bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            if (isSyncSample) {
38218bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
38228bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            }
38238bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
3824dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ++mCurrentSampleIndex;
3825dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3826dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
38273b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        if (!mIsAVC && !mIsHEVC) {
3828dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            *out = mBuffer;
3829dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
3830dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3831dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return OK;
3832dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3833dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3834dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Each NAL unit is split up into its constituent fragments and
3835dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // each one of them returned in its own buffer.
3836dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
38376064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(mBuffer->range_length() >= mNALLengthSize);
3838dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3839dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        const uint8_t *src =
3840dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
3841dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
38426064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t nal_size = parseNALSize(src);
3843e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
384429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("incomplete NAL unit.");
3845e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3846e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer->release();
3847e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer = NULL;
3848e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3849e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            return ERROR_MALFORMED;
3850e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        }
3851dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3852dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        MediaBuffer *clone = mBuffer->clone();
38537b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(clone != NULL);
38546064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
3855dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
38567b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(mBuffer != NULL);
3857dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mBuffer->set_range(
38586064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_offset() + mNALLengthSize + nal_size,
38596064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_length() - mNALLengthSize - nal_size);
3860dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3861dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (mBuffer->range_length() == 0) {
3862dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->release();
3863dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
3864dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3865dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3866dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        *out = clone;
3867dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3868dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        return OK;
3869dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    } else {
3870dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Whole NAL units are returned but each fragment is prefixed by
3871dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // the start code (0x00 00 00 01).
3872dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        ssize_t num_bytes_read = 0;
3873dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        int32_t drm = 0;
3874dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
3875dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (usesDRM) {
3876dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            num_bytes_read =
3877dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
3878dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
3879dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
3880dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
388120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
388220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (num_bytes_read < (ssize_t)size) {
388320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
388420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
388520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3886dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return ERROR_IO;
388720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
388820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3889dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (usesDRM) {
3890dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK(mBuffer != NULL);
3891dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            mBuffer->set_range(0, size);
38926064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
3893dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
3894dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            uint8_t *dstData = (uint8_t *)mBuffer->data();
3895dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size_t srcOffset = 0;
3896dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size_t dstOffset = 0;
3897e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3898dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            while (srcOffset < size) {
3899bfed843041b6aaec13ee19996748a7a1476db9c8Lajos Molnar                bool isMalFormed = !isInRange((size_t)0u, size, srcOffset, mNALLengthSize);
390034fe252c89e33572d01fea981b58d7b115e76164James Dong                size_t nalLength = 0;
390134fe252c89e33572d01fea981b58d7b115e76164James Dong                if (!isMalFormed) {
390234fe252c89e33572d01fea981b58d7b115e76164James Dong                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
390334fe252c89e33572d01fea981b58d7b115e76164James Dong                    srcOffset += mNALLengthSize;
3904bfed843041b6aaec13ee19996748a7a1476db9c8Lajos Molnar                    isMalFormed = !isInRange((size_t)0u, size, srcOffset, nalLength);
390534fe252c89e33572d01fea981b58d7b115e76164James Dong                }
3906e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
390734fe252c89e33572d01fea981b58d7b115e76164James Dong                if (isMalFormed) {
390829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                    ALOGE("Video is malformed");
3909dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    mBuffer->release();
3910dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    mBuffer = NULL;
3911dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return ERROR_MALFORMED;
3912dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
3913dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
3914dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                if (nalLength == 0) {
3915dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    continue;
3916dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
3917dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3918dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                CHECK(dstOffset + 4 <= mBuffer->size());
3919dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3920dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3921dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3922dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3923dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 1;
3924dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
3925dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                srcOffset += nalLength;
3926dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstOffset += nalLength;
3927dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
3928dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK_EQ(srcOffset, size);
3929dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK(mBuffer != NULL);
3930dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            mBuffer->set_range(0, dstOffset);
3931dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3932dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
393320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->meta_data()->clear();
393448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        mBuffer->meta_data()->setInt64(
39354678a6dc5f09008481524949a9667af5a6190374Andreas Huber                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
3936170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih        mBuffer->meta_data()->setInt64(
3937170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
3938abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3939abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (targetSampleTimeUs >= 0) {
3940abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            mBuffer->meta_data()->setInt64(
3941abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    kKeyTargetTime, targetSampleTimeUs);
3942abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3943abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
39448bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        if (isSyncSample) {
39458bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
39468bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        }
39478bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
394820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        ++mCurrentSampleIndex;
394920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
395020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        *out = mBuffer;
395120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
395220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
395320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
395420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
395520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
395620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
395705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::fragmentedRead(
395805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MediaBuffer **out, const ReadOptions *options) {
395905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
396005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Source::fragmentedRead");
396105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
396205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    CHECK(mStarted);
396305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
396405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    *out = NULL;
396505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
396605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t targetSampleTimeUs = -1;
396705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
396805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t seekTimeUs;
396905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ReadOptions::SeekMode mode;
397005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
397105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
397205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int numSidxEntries = mSegments.size();
397305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (numSidxEntries != 0) {
397405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            int64_t totalTime = 0;
397505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t totalOffset = mFirstMoofOffset;
397605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            for (int i = 0; i < numSidxEntries; i++) {
397705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                const SidxEntry *se = &mSegments[i];
397805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (totalTime + se->mDurationUs > seekTimeUs) {
397905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    // The requested time is somewhere in this segment
39803f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                    if ((mode == ReadOptions::SEEK_NEXT_SYNC && seekTimeUs > totalTime) ||
398105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        (mode == ReadOptions::SEEK_CLOSEST_SYNC &&
398205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        (seekTimeUs - totalTime) > (totalTime + se->mDurationUs - seekTimeUs))) {
398305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        // requested next sync, or closest sync and it was closer to the end of
398405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        // this segment
398505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        totalTime += se->mDurationUs;
398605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        totalOffset += se->mSize;
398705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    }
398805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    break;
398905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
399005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                totalTime += se->mDurationUs;
399105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                totalOffset += se->mSize;
399205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
3993ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentMoofOffset = totalOffset;
3994ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSamples.clear();
3995ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSampleIndex = 0;
3996ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            parseChunk(&totalOffset);
3997ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentTime = totalTime * mTimescale / 1000000ll;
3998ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen        } else {
3999ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            // without sidx boxes, we can only seek to 0
4000ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentMoofOffset = mFirstMoofOffset;
4001ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSamples.clear();
4002ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentSampleIndex = 0;
4003ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            off64_t tmp = mCurrentMoofOffset;
4004ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            parseChunk(&tmp);
4005ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            mCurrentTime = 0;
400605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
400705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
400805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer != NULL) {
400905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
401005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
401105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
401205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
401305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // fall through
401405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
401505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
401605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t offset = 0;
4017442cc6dc48f8188e097617f7f804c314a9dacd0eAndreas Huber    size_t size = 0;
401805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t cts = 0;
401905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    bool isSyncSample = false;
402005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    bool newBuffer = false;
402105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mBuffer == NULL) {
402205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        newBuffer = true;
402305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
402405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mCurrentSampleIndex >= mCurrentSamples.size()) {
40253f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            // move to next fragment if there is one
40263f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            if (mNextMoofOffset <= mCurrentMoofOffset) {
40273f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen                return ERROR_END_OF_STREAM;
40283f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen            }
4029ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            off64_t nextMoof = mNextMoofOffset;
403005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentMoofOffset = nextMoof;
403105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentSamples.clear();
403205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentSampleIndex = 0;
403305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            parseChunk(&nextMoof);
4034ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            if (mCurrentSampleIndex >= mCurrentSamples.size()) {
4035ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen                return ERROR_END_OF_STREAM;
4036ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen            }
403705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
403805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
403905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
404005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset = smpl->offset;
404105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size = smpl->size;
4042c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen        cts = mCurrentTime + smpl->compositionOffset;
404305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentTime += smpl->duration;
404405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        isSyncSample = (mCurrentSampleIndex == 0); // XXX
404505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
404605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        status_t err = mGroup->acquire_buffer(&mBuffer);
404705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
404805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (err != OK) {
404905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer == NULL);
405005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("acquire_buffer returned %d", err);
405105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return err;
405205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
405305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
405405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
405548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
405648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    const sp<MetaData> bufmeta = mBuffer->meta_data();
405748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    bufmeta->clear();
405848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (smpl->encryptedsizes.size()) {
405948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // store clear/encrypted lengths in metadata
406048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyPlainSizes, 0,
406148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->clearsizes.array(), smpl->clearsizes.size() * 4);
406248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyEncryptedSizes, 0,
406348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
406448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
406548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
406648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setInt32(kKeyCryptoMode, mCryptoMode);
406748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16);
406848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
406948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
40703b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar    if ((!mIsAVC && !mIsHEVC)|| mWantsNALFragments) {
407105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (newBuffer) {
407205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ssize_t num_bytes_read =
407305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
407405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
407505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (num_bytes_read < (ssize_t)size) {
407605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->release();
407705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer = NULL;
407805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
407905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                ALOGV("i/o error");
408005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_IO;
408105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
408205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
408305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
408405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, size);
408505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt64(
408605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
4087170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih            mBuffer->meta_data()->setInt64(
4088170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                    kKeyDuration, ((int64_t)smpl->duration * 1000000) / mTimescale);
408905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
409005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (targetSampleTimeUs >= 0) {
409105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->meta_data()->setInt64(
409205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        kKeyTargetTime, targetSampleTimeUs);
409305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
409405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
409505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (isSyncSample) {
409605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
409705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
409805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
409905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ++mCurrentSampleIndex;
410005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
410105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
41023b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        if (!mIsAVC && !mIsHEVC) {
410305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *out = mBuffer;
410405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
410505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
410605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return OK;
410705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
410805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
410905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // Each NAL unit is split up into its constituent fragments and
411005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // each one of them returned in its own buffer.
411105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
411205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(mBuffer->range_length() >= mNALLengthSize);
411305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
411405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const uint8_t *src =
411505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
411605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
411705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size_t nal_size = parseNALSize(src);
411805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
411905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGE("incomplete NAL unit.");
412005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
412105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
412205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
412305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
412405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
412505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
412605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
412705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MediaBuffer *clone = mBuffer->clone();
412805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(clone != NULL);
412905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
413005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
413105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(mBuffer != NULL);
413205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer->set_range(
413305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->range_offset() + mNALLengthSize + nal_size,
413405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->range_length() - mNALLengthSize - nal_size);
413505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
413605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer->range_length() == 0) {
413705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
413805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
413905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
414005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
414105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        *out = clone;
414205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
414305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
414405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
414505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV("whole NAL");
414605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // Whole NAL units are returned but each fragment is prefixed by
414705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // the start code (0x00 00 00 01).
414805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ssize_t num_bytes_read = 0;
414905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int32_t drm = 0;
415005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
415105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (usesDRM) {
415205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            num_bytes_read =
415305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
415405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else {
415505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
415605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
415705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
415805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (num_bytes_read < (ssize_t)size) {
415905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
416005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
416105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
416205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("i/o error");
416305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_IO;
416405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
416505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
416605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (usesDRM) {
416705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
416805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, size);
416905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
417005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else {
417105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            uint8_t *dstData = (uint8_t *)mBuffer->data();
417205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            size_t srcOffset = 0;
417305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            size_t dstOffset = 0;
417405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
417505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            while (srcOffset < size) {
4176bfed843041b6aaec13ee19996748a7a1476db9c8Lajos Molnar                bool isMalFormed = !isInRange((size_t)0u, size, srcOffset, mNALLengthSize);
417705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                size_t nalLength = 0;
417805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (!isMalFormed) {
417905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
418005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    srcOffset += mNALLengthSize;
4181bfed843041b6aaec13ee19996748a7a1476db9c8Lajos Molnar                    isMalFormed = !isInRange((size_t)0u, size, srcOffset, nalLength);
418205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
418305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
418405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (isMalFormed) {
418505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ALOGE("Video is malformed");
418605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    mBuffer->release();
418705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    mBuffer = NULL;
418805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return ERROR_MALFORMED;
418905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
419005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
419105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (nalLength == 0) {
419205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    continue;
419305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
419405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
419505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                CHECK(dstOffset + 4 <= mBuffer->size());
419605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
419705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
419805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
419905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
420005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 1;
420105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
420205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                srcOffset += nalLength;
420305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstOffset += nalLength;
420405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
420505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK_EQ(srcOffset, size);
420605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
420705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, dstOffset);
420805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
420905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
421005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer->meta_data()->setInt64(
421105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
4212170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih        mBuffer->meta_data()->setInt64(
4213170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih                kKeyDuration, ((int64_t)smpl->duration * 1000000) / mTimescale);
421405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
421505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (targetSampleTimeUs >= 0) {
421605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt64(
421705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    kKeyTargetTime, targetSampleTimeUs);
421805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
421905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
422005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (isSyncSample) {
422105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
422205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
422305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
422405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ++mCurrentSampleIndex;
422505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
422605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        *out = mBuffer;
422705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer = NULL;
422805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
422905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
423005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
423105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
423205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
4233bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas HuberMPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix(
4234bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        const char *mimePrefix) {
4235bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    for (Track *track = mFirstTrack; track != NULL; track = track->next) {
4236bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        const char *mime;
4237bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        if (track->meta != NULL
4238bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                && track->meta->findCString(kKeyMIMEType, &mime)
4239bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) {
4240bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber            return track;
4241bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        }
4242bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    }
4243bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber
4244bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    return NULL;
4245bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber}
4246bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber
42471b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool LegacySniffMPEG4(
4248693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
424920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[8];
425020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
425134769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    ssize_t n = source->readAt(4, header, sizeof(header));
425220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (n < (ssize_t)sizeof(header)) {
425320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return false;
425420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
425520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
425620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
4257b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8)
4258b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8)
42590dba73763a04d39faf999dcc5ef12af3c99535a7Andreas Huber        || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
4260ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
4261983b449a27b5fa91eca82ede5204b4341899be62Andreas Huber        || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
426218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
42635a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        *confidence = 0.4;
426420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
426520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return true;
426620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
426720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
426820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return false;
426920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
427020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
42711b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool isCompatibleBrand(uint32_t fourcc) {
42721b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    static const uint32_t kCompatibleBrands[] = {
42731b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', 'm'),
42741b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', '2'),
42751b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('a', 'v', 'c', '1'),
42763b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        FOURCC('h', 'v', 'c', '1'),
42773b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar        FOURCC('h', 'e', 'v', '1'),
42781b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('3', 'g', 'p', '4'),
42791b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '1'),
42801b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '2'),
42814cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong
42824cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        // Won't promise that the following file types can be played.
42834cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        // Just give these file types a chance.
42844cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        FOURCC('q', 't', ' ', ' '),  // Apple's QuickTime
42854cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        FOURCC('M', 'S', 'N', 'V'),  // Sony's PSP
428658fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber
428758fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber        FOURCC('3', 'g', '2', 'a'),  // 3GPP2
428858fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber        FOURCC('3', 'g', '2', 'b'),
42891b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    };
42901b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
42911b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    for (size_t i = 0;
42921b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]);
42931b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         ++i) {
42941b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        if (kCompatibleBrands[i] == fourcc) {
42951b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            return true;
42961b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
42971b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
42981b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
42991b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
43001b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
43011b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
43021b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// Attempt to actually parse the 'ftyp' atom and determine if a suitable
43031b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// compatible brand is present.
4304a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// Also try to identify where this file's metadata ends
4305a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// (end of the 'moov' atom) and report it to the caller as part of
4306a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// the metadata.
43071b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool BetterSniffMPEG4(
4308a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
4309a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        sp<AMessage> *meta) {
4310a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    // We scan up to 128 bytes to identify this file as an MP4.
4311a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    static const off64_t kMaxScanOffset = 128ll;
43121b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4313a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    off64_t offset = 0ll;
4314a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    bool foundGoodFileType = false;
4315a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    off64_t moovAtomEndOffset = -1ll;
4316a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    bool done = false;
43171b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4318a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    while (!done && offset < kMaxScanOffset) {
4319a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint32_t hdr[2];
4320a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        if (source->readAt(offset, hdr, 8) < 8) {
4321a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            return false;
4322a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        }
4323a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4324a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint64_t chunkSize = ntohl(hdr[0]);
4325a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint32_t chunkType = ntohl(hdr[1]);
4326a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        off64_t chunkDataOffset = offset + 8;
4327a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4328a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        if (chunkSize == 1) {
4329a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            if (source->readAt(offset + 8, &chunkSize, 8) < 8) {
43301b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                return false;
43311b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
43321b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4333a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            chunkSize = ntoh64(chunkSize);
4334a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            chunkDataOffset += 8;
4335a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4336a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            if (chunkSize < 16) {
4337a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                // The smallest valid chunk is 16 bytes long in this case.
4338a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                return false;
4339a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            }
4340a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        } else if (chunkSize < 8) {
4341a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            // The smallest valid chunk is 8 bytes long.
4342a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            return false;
4343a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        }
4344a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4345a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        off64_t chunkDataSize = offset + chunkSize - chunkDataOffset;
4346a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
434705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        char chunkstring[5];
434805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MakeFourCCString(chunkType, chunkstring);
4349a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGV("saw chunk type %s, size %" PRIu64 " @ %lld", chunkstring, chunkSize, offset);
4350a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        switch (chunkType) {
4351a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            case FOURCC('f', 't', 'y', 'p'):
4352a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            {
4353a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                if (chunkDataSize < 8) {
4354a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    return false;
4355a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
4356a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4357a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4;
4358a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
4359a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (i == 1) {
4360a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        // Skip this index, it refers to the minorVersion,
4361a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        // not a brand.
4362a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        continue;
4363a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
4364a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4365a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    uint32_t brand;
4366a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (source->readAt(
4367a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                                chunkDataOffset + 4 * i, &brand, 4) < 4) {
4368a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        return false;
4369a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
4370a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4371a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    brand = ntohl(brand);
4372a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4373a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (isCompatibleBrand(brand)) {
4374a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        foundGoodFileType = true;
4375a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        break;
4376a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
4377a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
4378a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4379a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                if (!foundGoodFileType) {
4380a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    return false;
4381a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
4382a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
43831b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                break;
43841b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
4385a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4386a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            case FOURCC('m', 'o', 'o', 'v'):
4387a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            {
4388a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                moovAtomEndOffset = offset + chunkSize;
4389a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4390a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                done = true;
4391a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                break;
4392a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            }
4393a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4394a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            default:
4395a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                break;
43961b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
4397a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4398a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        offset += chunkSize;
43991b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
44001b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4401a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (!foundGoodFileType) {
44021b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return false;
44031b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
44041b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
44051b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
44065a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber    *confidence = 0.4f;
44071b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4408a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (moovAtomEndOffset >= 0) {
4409a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        *meta = new AMessage;
4410a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        (*meta)->setInt64("meta-data-size", moovAtomEndOffset);
4411a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4412456caf3f5f0af673dc120c17c23635f40d8f5ac2Andreas Huber        ALOGV("found metadata size: %lld", moovAtomEndOffset);
4413a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    }
4414a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
44151b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return true;
44161b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
44171b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
44181b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberbool SniffMPEG4(
44195a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
4420a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        sp<AMessage> *meta) {
4421a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (BetterSniffMPEG4(source, mimeType, confidence, meta)) {
44221b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
44231b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
44241b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
44251b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    if (LegacySniffMPEG4(source, mimeType, confidence)) {
44265ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Identified supported mpeg4 through LegacySniffMPEG4.");
44271b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
44281b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
44291b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
44301b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
44311b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
44321b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
443320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
4434