MPEG4Extractor.cpp revision 937c6bedd4b6e5c6cb29a238eb459047dedd3486
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"
1920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/Log.h>
2020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2166326a5ee0869f1ee4d136a477e6effba428b3cbAndreas Huber#include "include/MPEG4Extractor.h"
2289e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber#include "include/SampleTable.h"
237a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang#include "include/ESDS.h"
2489e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber
2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <ctype.h>
2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <stdint.h>
2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <stdlib.h>
2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <string.h>
2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke#include <media/stagefright/foundation/ABitReader.h>
31d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson#include <media/stagefright/foundation/ABuffer.h>
32ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#include <media/stagefright/foundation/ADebug.h>
33a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber#include <media/stagefright/foundation/AMessage.h>
3467a30ebfe785f7cd5ecfb0d2fb487e54536a3d48Lajos Molnar#include <media/stagefright/foundation/AUtils.h>
3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
3620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBufferGroup.h>
3718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/String8.h>
4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
42937c6bedd4b6e5c6cb29a238eb459047dedd3486Wei Jia#ifndef UINT32_MAX
43937c6bedd4b6e5c6cb29a238eb459047dedd3486Wei Jia#define UINT32_MAX       (4294967295U)
44937c6bedd4b6e5c6cb29a238eb459047dedd3486Wei Jia#endif
45937c6bedd4b6e5c6cb29a238eb459047dedd3486Wei Jia
4620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
4720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Source : public MediaSource {
4920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Caller retains ownership of both "dataSource" and "sampleTable".
51693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    MPEG4Source(const sp<MetaData> &format,
52693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber                const sp<DataSource> &dataSource,
5348c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                int32_t timeScale,
5405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                const sp<SampleTable> &sampleTable,
5505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                Vector<SidxEntry> &sidx,
5605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                off64_t firstMoofOffset);
5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t start(MetaData *params = NULL);
5920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t stop();
6020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual sp<MetaData> getFormat();
6220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL);
6405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    virtual status_t fragmentedRead(MediaBuffer **buffer, const ReadOptions *options = NULL);
6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huberprotected:
67693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    virtual ~MPEG4Source();
68693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber
6920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
707b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex mLock;
717b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
7220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mFormat;
73693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<DataSource> mDataSource;
7420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t mTimescale;
75693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<SampleTable> mSampleTable;
7620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t mCurrentSampleIndex;
7705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t mCurrentFragmentIndex;
7805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Vector<SidxEntry> &mSegments;
7905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mFirstMoofOffset;
8005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mCurrentMoofOffset;
8105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mNextMoofOffset;
8205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t mCurrentTime;
8305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int32_t mLastParsedTrackId;
8405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int32_t mTrackId;
8520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
86ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int32_t mCryptoMode;    // passed in from extractor
87ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int32_t mDefaultIVSize; // passed in from extractor
88ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t mCryptoKey[16]; // passed in from extractor
89ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentAuxInfoType;
90ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentAuxInfoTypeParameter;
9148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    int32_t mCurrentDefaultSampleInfoSize;
92ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoCount;
93ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoAllocSize;
94ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t* mCurrentSampleInfoSizes;
95ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoOffsetCount;
96ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoOffsetsAllocSize;
97ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint64_t* mCurrentSampleInfoOffsets;
98ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
9920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mIsAVC;
1006064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    size_t mNALLengthSize;
1016064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mStarted;
10320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBufferGroup *mGroup;
10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *mBuffer;
10720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
108dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool mWantsNALFragments;
10920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1100024245e134467d120b40099da16c467dc365e76Andreas Huber    uint8_t *mSrcBuffer;
1110024245e134467d120b40099da16c467dc365e76Andreas Huber
1126064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    size_t parseNALSize(const uint8_t *data) const;
11305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseChunk(off64_t *offset);
11405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseTrackFragmentHeader(off64_t offset, off64_t size);
11505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseTrackFragmentRun(off64_t offset, off64_t size);
116ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    status_t parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size);
117ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    status_t parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size);
11805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
11905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    struct TrackFragmentHeaderInfo {
12005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        enum Flags {
12105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kBaseDataOffsetPresent         = 0x01,
12205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kSampleDescriptionIndexPresent = 0x02,
12305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleDurationPresent  = 0x08,
12405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleSizePresent      = 0x10,
12505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleFlagsPresent     = 0x20,
12605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDurationIsEmpty               = 0x10000,
12705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        };
12805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
12905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mTrackID;
13005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mFlags;
13105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint64_t mBaseDataOffset;
13205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mSampleDescriptionIndex;
13305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleDuration;
13405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleSize;
13505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleFlags;
13605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
13705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint64_t mDataOffset;
13805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
13905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    TrackFragmentHeaderInfo mTrackFragmentHeaderInfo;
14005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
14105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    struct Sample {
14205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t offset;
14305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size_t size;
14405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t duration;
145ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        uint8_t iv[16];
146ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Vector<size_t> clearsizes;
147ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Vector<size_t> encryptedsizes;
14805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
14905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Vector<Sample> mCurrentSamples;
1506064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
15120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source(const MPEG4Source &);
15220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source &operator=(const MPEG4Source &);
15320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
15420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This custom data source wraps an existing one and satisfies requests
15650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// falling entirely within a cached range from the cache while forwarding
15750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// all remaining requests to the wrapped datasource.
15850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This is used to cache the full sampletable metadata for a single track,
15950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// possibly wrapping multiple times to cover all tracks, i.e.
16050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// Each MPEG4DataSource caches the sampletable metadata for a single track.
16150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
16250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstruct MPEG4DataSource : public DataSource {
16350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource(const sp<DataSource> &source);
16450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
16550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual status_t initCheck() const;
166c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
167c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    virtual status_t getSize(off64_t *size);
16850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual uint32_t flags();
16950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
170c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    status_t setCachedRange(off64_t offset, size_t size);
17150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprotected:
17350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual ~MPEG4DataSource();
17450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprivate:
17650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex mLock;
17750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    sp<DataSource> mSource;
179c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t mCachedOffset;
18050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    size_t mCachedSize;
18150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    uint8_t *mCache;
18250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    void clearCache();
18450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource(const MPEG4DataSource &);
18650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource &operator=(const MPEG4DataSource &);
18750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber};
18850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source)
19050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    : mSource(source),
19150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCachedOffset(0),
19250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCachedSize(0),
19350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCache(NULL) {
19450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
19550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::~MPEG4DataSource() {
19750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    clearCache();
19850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
19950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
20050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Hubervoid MPEG4DataSource::clearCache() {
20150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (mCache) {
20250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        free(mCache);
20350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        mCache = NULL;
20450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
20550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
20650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedOffset = 0;
20750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedSize = 0;
20850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
20950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
21050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstatus_t MPEG4DataSource::initCheck() const {
21150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->initCheck();
21250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
21350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
214c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongssize_t MPEG4DataSource::readAt(off64_t offset, void *data, size_t size) {
21550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex::Autolock autoLock(mLock);
21650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
21767a30ebfe785f7cd5ecfb0d2fb487e54536a3d48Lajos Molnar    if (isInRange(mCachedOffset, mCachedSize, offset, size)) {
21850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        memcpy(data, &mCache[offset - mCachedOffset], size);
21950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return size;
22050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
22150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
22250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->readAt(offset, data, size);
22350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
22450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
225c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4DataSource::getSize(off64_t *size) {
22650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->getSize(size);
22750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
22850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
22950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberuint32_t MPEG4DataSource::flags() {
23050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->flags();
23150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
23250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
233c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4DataSource::setCachedRange(off64_t offset, size_t size) {
23450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex::Autolock autoLock(mLock);
23550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
23650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    clearCache();
23750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
23850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCache = (uint8_t *)malloc(size);
23950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
24050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (mCache == NULL) {
24150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return -ENOMEM;
24250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
24350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
24450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedOffset = offset;
24550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedSize = size;
24650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
24750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    ssize_t err = mSource->readAt(mCachedOffset, mCache, mCachedSize);
24850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
24950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (err < (ssize_t)size) {
25050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        clearCache();
25150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
25250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return ERROR_IO;
25350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
25450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
25550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return OK;
25650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
25750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
25850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber////////////////////////////////////////////////////////////////////////////////
25950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
26020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatic void hexdump(const void *_data, size_t size) {
26120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const uint8_t *data = (const uint8_t *)_data;
26220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t offset = 0;
26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (offset < size) {
26420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf("0x%04x  ", offset);
26520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        size_t n = size - offset;
26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (n > 16) {
26820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            n = 16;
26920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
27020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < 16; ++i) {
27220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (i == 8) {
27320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(" ");
27420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
27520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (offset + i < size) {
27720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%02x ", data[offset + i]);
27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
27920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("   ");
28020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
28120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
28220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf(" ");
28420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < n; ++i) {
28620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (isprint(data[offset + i])) {
28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%c", data[offset + i]);
28820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(".");
29020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf("\n");
29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        offset += 16;
29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
29820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huberstatic const char *FourCC2MIME(uint32_t fourcc) {
30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch (fourcc) {
30120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
30218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AAC;
30320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
30518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_NB;
30620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
307371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
30818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_WB;
309371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
31020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
31118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_MPEG4;
31220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
314e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('h', '2', '6', '3'):
315e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('H', '2', '6', '3'):
31618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_H263;
31720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
31918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_AVC;
32020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
322dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(!"should not be here.");
32320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
32420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
32520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
32620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissenstatic bool AdjustChannelsAndRate(uint32_t fourcc, uint32_t *channels, uint32_t *rate) {
32848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, FourCC2MIME(fourcc))) {
32948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // AMR NB audio is always mono, 8kHz
33048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *channels = 1;
33148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *rate = 8000;
33248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return true;
33348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, FourCC2MIME(fourcc))) {
33448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // AMR WB audio is always mono, 16kHz
33548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *channels = 1;
33648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *rate = 16000;
33748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return true;
33848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
33948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    return false;
34048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen}
34148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
342693d271e62a3726689ff68f4505ba49228eb94b2Andreas HuberMPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
34305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    : mSidxDuration(0),
34405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mMoofOffset(0),
34505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mDataSource(source),
346bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber      mInitCheck(NO_INIT),
3477be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber      mHasVideo(false),
348fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen      mHeaderTimescale(0),
34920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mFirstTrack(NULL),
35072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber      mLastTrack(NULL),
351dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mFileMetaData(new MetaData),
352dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mFirstSINF(NULL),
353dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mIsDrm(false) {
35420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
35520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Extractor::~MPEG4Extractor() {
35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        Track *next = track->next;
36020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete track;
36220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = next;
36320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
36420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFirstTrack = mLastTrack = NULL;
365dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
366dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    SINF *sinf = mFirstSINF;
367dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (sinf) {
368dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        SINF *next = sinf->next;
369dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        delete sinf->IPMPData;
370dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        delete sinf;
371dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf = next;
372dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
373dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    mFirstSINF = NULL;
374ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
375ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mPssh.size(); i++) {
376ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        delete [] mPssh[i].data;
377ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
37820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
37920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
38005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenuint32_t MPEG4Extractor::flags() const {
38105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return CAN_PAUSE |
38205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ((mMoofOffset == 0 || mSidxEntries.size() != 0) ?
38305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    (CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK) : 0);
38405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
38505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3867be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Hubersp<MetaData> MPEG4Extractor::getMetaData() {
3877be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    status_t err;
3887be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    if ((err = readMetaData()) != OK) {
38972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return new MetaData;
3907be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    }
3917be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
39272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return mFileMetaData;
3937be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber}
3947be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
395693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersize_t MPEG4Extractor::countTracks() {
39620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
39720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
398ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        ALOGV("MPEG4Extractor::countTracks: no tracks");
399693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return 0;
40020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
40120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
402693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    size_t n = 0;
40320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
40420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
405693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        ++n;
40620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
40720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
40820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
409ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("MPEG4Extractor::countTracks: %d tracks", n);
410693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    return n;
41120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
41220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4137e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Hubersp<MetaData> MPEG4Extractor::getTrackMetaData(
4147e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        size_t index, uint32_t flags) {
41520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
41620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
41720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return NULL;
41820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
41920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
42020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
42120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
42220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
42320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
42420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
42520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
42620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
42720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
42820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
42920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
430371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
431371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
432371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
433371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
4347e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    if ((flags & kIncludeExtensiveMetaData)
4357e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            && !track->includes_expensive_metadata) {
4367e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        track->includes_expensive_metadata = true;
4377e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
4387e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        const char *mime;
4397e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        CHECK(track->meta->findCString(kKeyMIMEType, &mime));
4407e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        if (!strncasecmp("video/", mime, 6)) {
44105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (mMoofOffset > 0) {
44205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                int64_t duration;
44305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (track->meta->findInt64(kKeyDuration, &duration)) {
44405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    // nothing fancy, just pick a frame near 1/4th of the duration
44505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    track->meta->setInt64(
44605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            kKeyThumbnailTime, duration / 4);
44705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
44805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            } else {
44905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t sampleIndex;
45005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t sampleTime;
45105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK
45205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        && track->sampleTable->getMetaDataForSample(
45305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            sampleIndex, NULL /* offset */, NULL /* size */,
45405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            &sampleTime) == OK) {
45505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    track->meta->setInt64(
45605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            kKeyThumbnailTime,
45705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            ((int64_t)sampleTime * 1000000) / track->timescale);
45805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
4597e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            }
4607e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        }
4617e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    }
4627e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
46320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return track->meta;
46420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
46520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
46648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissenstatic void MakeFourCCString(uint32_t x, char *s) {
46748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[0] = x >> 24;
46848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[1] = (x >> 16) & 0xff;
46948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[2] = (x >> 8) & 0xff;
47048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[3] = x & 0xff;
47148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[4] = '\0';
47248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen}
47348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
47420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Extractor::readMetaData() {
475bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    if (mInitCheck != NO_INIT) {
476bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        return mInitCheck;
47720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
47820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
479c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = 0;
48020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
48105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    while (true) {
48205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        err = parseChunk(&offset, 0);
48305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (err == OK) {
48405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            continue;
48505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
48605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
48705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t hdr[2];
48805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mDataSource->readAt(offset, hdr, 8) < 8) {
48905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
49005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
49105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t chunk_type = ntohl(hdr[1]);
49205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (chunk_type == FOURCC('s', 'i', 'd', 'x')) {
49305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            // parse the sidx box too
49405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            continue;
49505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
49605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            // store the offset of the first segment
49705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mMoofOffset = offset;
49805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
49905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        break;
50020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
5017be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
502bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    if (mInitCheck == OK) {
50372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        if (mHasVideo) {
504bc8b5faec8a0a9ad7c8d94945e7b000d63f0afe6Andreas Huber            mFileMetaData->setCString(
505bc8b5faec8a0a9ad7c8d94945e7b000d63f0afe6Andreas Huber                    kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG4);
50672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else {
50772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
50872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
50972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
5104678a6dc5f09008481524949a9667af5a6190374Andreas Huber        mInitCheck = OK;
511bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    } else {
512bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        mInitCheck = err;
51320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
51420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
515bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    CHECK_NE(err, (status_t)NO_INIT);
516ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
517ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // copy pssh data into file metadata
518ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int psshsize = 0;
519ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mPssh.size(); i++) {
520ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        psshsize += 20 + mPssh[i].datalen;
521ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
522ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (psshsize) {
523ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        char *buf = (char*)malloc(psshsize);
524ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        char *ptr = buf;
525ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        for (size_t i = 0; i < mPssh.size(); i++) {
526ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memcpy(ptr, mPssh[i].uuid, 20); // uuid + length
527ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memcpy(ptr + 20, mPssh[i].data, mPssh[i].datalen);
528ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ptr += (20 + mPssh[i].datalen);
529ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
530ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mFileMetaData->setData(kKeyPssh, 'pssh', buf, psshsize);
531ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        free(buf);
532ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
533bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    return mInitCheck;
53420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
53520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
536dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wangchar* MPEG4Extractor::getDrmTrackInfo(size_t trackID, int *len) {
537dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mFirstSINF == NULL) {
538dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return NULL;
539dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
540dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
541dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    SINF *sinf = mFirstSINF;
542dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (sinf && (trackID != sinf->trackID)) {
543dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf = sinf->next;
544dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
545dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
546dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (sinf == NULL) {
547dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return NULL;
548dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
549dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
550dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    *len = sinf->len;
551dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return sinf->IPMPData;
552dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
553dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
554dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang// Reads an encoded integer 7 bits at a time until it encounters the high bit clear.
55556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenstatic int32_t readSize(off64_t offset,
556dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        const sp<DataSource> DataSource, uint8_t *numOfBytes) {
557dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint32_t size = 0;
558dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t data;
559dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    bool moreData = true;
560dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    *numOfBytes = 0;
561dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
562dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (moreData) {
563dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (DataSource->readAt(offset, &data, 1) < 1) {
564dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return -1;
565dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
566dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        offset ++;
567dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        moreData = (data >= 128) ? true : false;
568dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        size = (size << 7) | (data & 0x7f); // Take last 7 bits
569dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        (*numOfBytes) ++;
570dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
571dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
572dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return size;
573dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
574dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
575c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseDrmSINF(off64_t *offset, off64_t data_offset) {
576dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t updateIdTag;
577dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
578dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
579dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
580dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset ++;
581dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
582dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (0x01/*OBJECT_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
583dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
584dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
585dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
586dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t numOfBytes;
587dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    int32_t size = readSize(data_offset, mDataSource, &numOfBytes);
588dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size < 0) {
589dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
590dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
591dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    int32_t classSize = size;
592dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset += numOfBytes;
593dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
594dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while(size >= 11 ) {
595dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t descriptorTag;
596dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, &descriptorTag, 1) < 1) {
597dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
598dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
599dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset ++;
600dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
601dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (0x11/*OBJECT_DESCRIPTOR_ID_TAG*/ != descriptorTag) {
602dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
603dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
604dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
605dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t buffer[8];
606dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        //ObjectDescriptorID and ObjectDescriptor url flag
607dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, buffer, 2) < 2) {
608dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
609dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
610dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset += 2;
611dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
612dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if ((buffer[1] >> 5) & 0x0001) { //url flag is set
613dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
614dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
615dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
616dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, buffer, 8) < 8) {
617dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
618dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
619dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset += 8;
620dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
621dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if ((0x0F/*ES_ID_REF_TAG*/ != buffer[1])
622dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                || ( 0x0A/*IPMP_DESCRIPTOR_POINTER_ID_TAG*/ != buffer[5])) {
623dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_MALFORMED;
624dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
625dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
626dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        SINF *sinf = new SINF;
627dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->trackID = U16_AT(&buffer[3]);
628dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->IPMPDescriptorID = buffer[7];
629dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf->next = mFirstSINF;
630dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        mFirstSINF = sinf;
631dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
632dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        size -= (8 + 2 + 1);
633dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
634dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
635dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size != 0) {
636dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
637dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
638dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
639dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
640dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
641dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
642dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset ++;
643dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
644dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if(0x05/*IPMP_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
645dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
646dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
647dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
648dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    size = readSize(data_offset, mDataSource, &numOfBytes);
649dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size < 0) {
650dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_IO;
651dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
652dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    classSize = size;
653dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    data_offset += numOfBytes;
654dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
655dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (size > 0) {
656dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        uint8_t tag;
657dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        int32_t dataLen;
658dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDataSource->readAt(data_offset, &tag, 1) < 1) {
659dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return ERROR_IO;
660dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
661dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        data_offset ++;
662dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
663dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (0x0B/*IPMP_DESCRIPTOR_ID_TAG*/ == tag) {
664dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            uint8_t id;
665dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            dataLen = readSize(data_offset, mDataSource, &numOfBytes);
666dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (dataLen < 0) {
667dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
668dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            } else if (dataLen < 4) {
669dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
670dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
671dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset += numOfBytes;
672dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
673dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (mDataSource->readAt(data_offset, &id, 1) < 1) {
674dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
675dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
676dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset ++;
677dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
678dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            SINF *sinf = mFirstSINF;
679dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            while (sinf && (sinf->IPMPDescriptorID != id)) {
680dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                sinf = sinf->next;
681dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
682dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (sinf == NULL) {
683dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
684dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
685dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            sinf->len = dataLen - 3;
686dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            sinf->IPMPData = new char[sinf->len];
687dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
688dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (mDataSource->readAt(data_offset + 2, sinf->IPMPData, sinf->len) < sinf->len) {
689dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
690dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
691dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset += sinf->len;
692dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
693dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size -= (dataLen + numOfBytes + 1);
694dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
695dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
696dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
697dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size != 0) {
698dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
699dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
700dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
701dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return UNKNOWN_ERROR;  // Return a dummy error.
702dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
703dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
70472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstruct PathAdder {
70572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder(Vector<uint32_t> *path, uint32_t chunkType)
70672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        : mPath(path) {
70772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        mPath->push(chunkType);
70872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
70972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
71072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    ~PathAdder() {
71172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        mPath->pop();
71272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
71372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
71472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberprivate:
71572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    Vector<uint32_t> *mPath;
71672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
71772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder(const PathAdder &);
71872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder &operator=(const PathAdder &);
71972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber};
72072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
72172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic bool underMetaDataPath(const Vector<uint32_t> &path) {
72272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return path.size() >= 5
72372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[0] == FOURCC('m', 'o', 'o', 'v')
72472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[1] == FOURCC('u', 'd', 't', 'a')
72572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[2] == FOURCC('m', 'e', 't', 'a')
72672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[3] == FOURCC('i', 'l', 's', 't');
72772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
72872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
72972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber// Given a time in seconds since Jan 1 1904, produce a human-readable string.
73072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic void convertTimeToDate(int64_t time_1904, String8 *s) {
73172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    time_t time_1970 = time_1904 - (((66 * 365 + 17) * 24) * 3600);
73272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
73372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    char tmp[32];
73472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", gmtime(&time_1970));
73572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
73672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    s->setTo(tmp);
73772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
73872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
739c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
7405d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    ALOGV("entering parseChunk %lld/%d", *offset, depth);
74120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t hdr[2];
74234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
74320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_IO;
74420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
74520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint64_t chunk_size = ntohl(hdr[0]);
74620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t chunk_type = ntohl(hdr[1]);
747c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t data_offset = *offset + 8;
74820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
74920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (chunk_size == 1) {
75034769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
75120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_IO;
75220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
75320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        chunk_size = ntoh64(chunk_size);
75420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        data_offset += 8;
75571b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber
75671b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        if (chunk_size < 16) {
75771b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber            // The smallest valid chunk is 16 bytes long in this case.
75871b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber            return ERROR_MALFORMED;
75971b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        }
76071b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber    } else if (chunk_size < 8) {
76171b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        // The smallest valid chunk is 8 bytes long.
76271b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        return ERROR_MALFORMED;
76320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
76520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    char chunk[5];
76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MakeFourCCString(chunk_type, chunk);
76705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("chunk: %s @ %lld, %d", chunk, *offset, depth);
76820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#if 0
77020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static const char kWhitespace[] = "                                        ";
77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
77220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size);
77320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    char buffer[256];
775ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    size_t n = chunk_size;
776ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    if (n > sizeof(buffer)) {
777ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        n = sizeof(buffer);
778ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    }
779ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    if (mDataSource->readAt(*offset, buffer, n)
780ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber            < (ssize_t)n) {
781ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        return ERROR_IO;
78220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
783ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
784ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    hexdump(buffer, n);
78520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#endif
78620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
78772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder autoAdder(&mPath, chunk_type);
78872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
789c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t chunk_data_size = *offset + chunk_size - data_offset;
79020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
79172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (chunk_type != FOURCC('c', 'p', 'r', 't')
792515e855eae78aa495da58356486aaa666cb57fd1James Dong            && chunk_type != FOURCC('c', 'o', 'v', 'r')
79372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            && mPath.size() == 5 && underMetaDataPath(mPath)) {
794c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t stop_offset = *offset + chunk_size;
79572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        *offset = data_offset;
79672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        while (*offset < stop_offset) {
79772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            status_t err = parseChunk(offset, depth + 1);
79872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (err != OK) {
79972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return err;
80072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
80172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
802bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
803bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (*offset != stop_offset) {
804bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
805bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
80672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
80772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return OK;
80872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
80972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
81020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch(chunk_type) {
81120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'v'):
81220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'k'):
81320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'i', 'a'):
81420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'i', 'n', 'f'):
81520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('d', 'i', 'n', 'f'):
81620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'b', 'l'):
81720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'v', 'e', 'x'):
81820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'f'):
81920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'f'):
82020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'f', 'r', 'a'):
82172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('u', 'd', 't', 'a'):
82272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('i', 'l', 's', 't'):
823ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'i', 'n', 'f'):
824ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'c', 'h', 'i'):
8250a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        case FOURCC('e', 'd', 't', 's'):
82620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
82750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
8283856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size);
82950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
830b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                if (mDataSource->flags()
831b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                        & (DataSource::kWantsPrefetching
832b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                            | DataSource::kIsCachingDataSource)) {
83350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    sp<MPEG4DataSource> cachedSource =
83450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                        new MPEG4DataSource(mDataSource);
83550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
83650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
83750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                        mDataSource = cachedSource;
83850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    }
83950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                }
8401edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber
8411edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber                mLastTrack->sampleTable = new SampleTable(mDataSource);
84250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            }
84350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
8446f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber            bool isTrack = false;
845bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (chunk_type == FOURCC('t', 'r', 'a', 'k')) {
8466f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                isTrack = true;
8476f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
848bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                Track *track = new Track;
849bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->next = NULL;
850bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                if (mLastTrack) {
851bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    mLastTrack->next = track;
852bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                } else {
853bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    mFirstTrack = track;
854bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                }
855bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                mLastTrack = track;
856bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
857bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->meta = new MetaData;
858bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->includes_expensive_metadata = false;
8596f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                track->skipTrack = false;
860bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->timescale = 0;
861bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->meta->setCString(kKeyMIMEType, "application/octet-stream");
862bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
863bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
864c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
86520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset;
86620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
86720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
86820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
86920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
87020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
87120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
87220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
873bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
874bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
875bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
876bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
8776f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber            if (isTrack) {
8786f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                if (mLastTrack->skipTrack) {
8796f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    Track *cur = mFirstTrack;
8806f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
8816f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    if (cur == mLastTrack) {
8826f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        delete cur;
8836f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        mFirstTrack = mLastTrack = NULL;
8846f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    } else {
8856f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        while (cur && cur->next != mLastTrack) {
8866f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                            cur = cur->next;
8876f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        }
8886f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        cur->next = NULL;
8896f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        delete mLastTrack;
8906f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        mLastTrack = cur;
8916f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    }
8926f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
8936f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    return OK;
8946f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                }
8956f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
896bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                status_t err = verifyTrack(mLastTrack);
897bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
898bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                if (err != OK) {
899bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    return err;
900bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                }
901bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
902bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                mInitCheck = OK;
90320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
904dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                if (!mIsDrm) {
905dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return UNKNOWN_ERROR;  // Return a dummy error.
906dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                } else {
907dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return OK;
908dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
90920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
91020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
91120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
91220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9130a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        case FOURCC('e', 'l', 's', 't'):
9140a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        {
9150a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            // See 14496-12 8.6.6
9160a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            uint8_t version;
9170a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (mDataSource->readAt(data_offset, &version, 1) < 1) {
9180a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                return ERROR_IO;
9190a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
9200a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9210a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            uint32_t entry_count;
9220a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (!mDataSource->getUInt32(data_offset + 4, &entry_count)) {
9230a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                return ERROR_IO;
9240a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
9250a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9260a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (entry_count != 1) {
9270a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                // we only support a single entry at the moment, for gapless playback
9280a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                ALOGW("ignoring edit list with %d entries", entry_count);
929fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            } else if (mHeaderTimescale == 0) {
930210efd48ed21ca0084d9440f9a1db7d9878f8094Marco Nelissen                ALOGW("ignoring edit list because timescale is 0");
9310a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            } else {
9320a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                off64_t entriesoffset = data_offset + 8;
9330a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                uint64_t segment_duration;
9340a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int64_t media_time;
9350a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9360a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                if (version == 1) {
9370a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    if (!mDataSource->getUInt64(entriesoffset, &segment_duration) ||
9380a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                            !mDataSource->getUInt64(entriesoffset + 8, (uint64_t*)&media_time)) {
9390a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        return ERROR_IO;
9400a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    }
9410a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                } else if (version == 0) {
9420a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    uint32_t sd;
9430a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int32_t mt;
9440a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    if (!mDataSource->getUInt32(entriesoffset, &sd) ||
9450a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                            !mDataSource->getUInt32(entriesoffset + 4, (uint32_t*)&mt)) {
9460a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        return ERROR_IO;
9470a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    }
9480a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    segment_duration = sd;
9490a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    media_time = mt;
9500a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                } else {
9510a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    return ERROR_IO;
9520a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                }
9530a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
954fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                uint64_t halfscale = mHeaderTimescale / 2;
955fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                segment_duration = (segment_duration * 1000000 + halfscale)/ mHeaderTimescale;
956fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                media_time = (media_time * 1000000 + halfscale) / mHeaderTimescale;
9570a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9580a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int64_t duration;
9590a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int32_t samplerate;
9600a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                if (mLastTrack->meta->findInt64(kKeyDuration, &duration) &&
9610a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        mLastTrack->meta->findInt32(kKeySampleRate, &samplerate)) {
9620a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9630a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t delay = (media_time  * samplerate + 500000) / 1000000;
9640a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
9650a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9660a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t paddingus = duration - (segment_duration + media_time);
967be1195a6d5e6dd4299da344cf9905dd6a12dc4efMarco Nelissen                    if (paddingus < 0) {
968be1195a6d5e6dd4299da344cf9905dd6a12dc4efMarco Nelissen                        // track duration from media header (which is what kKeyDuration is) might
969be1195a6d5e6dd4299da344cf9905dd6a12dc4efMarco Nelissen                        // be slightly shorter than the segment duration, which would make the
970be1195a6d5e6dd4299da344cf9905dd6a12dc4efMarco Nelissen                        // padding negative. Clamp to zero.
971be1195a6d5e6dd4299da344cf9905dd6a12dc4efMarco Nelissen                        paddingus = 0;
972be1195a6d5e6dd4299da344cf9905dd6a12dc4efMarco Nelissen                    }
9730a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t paddingsamples = (paddingus * samplerate + 500000) / 1000000;
9740a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    mLastTrack->meta->setInt32(kKeyEncoderPadding, paddingsamples);
9750a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                }
9760a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
9770a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            *offset += chunk_size;
9780a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            break;
9790a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        }
9800a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
981ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('f', 'r', 'm', 'a'):
982ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
98348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t original_fourcc;
984ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset, &original_fourcc, 4) < 4) {
985ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
986ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
987ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            original_fourcc = ntohl(original_fourcc);
988ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("read original format: %d", original_fourcc);
989ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc));
99048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t num_channels = 0;
99148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t sample_rate = 0;
99248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (AdjustChannelsAndRate(original_fourcc, &num_channels, &sample_rate)) {
99348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
99448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
99548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            }
996ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
997ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
998ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
999ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1000ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('t', 'e', 'n', 'c'):
1001ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
1002ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (chunk_size < 32) {
1003ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1004ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1005ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1006ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // tenc box contains 1 byte version, 3 byte flags, 3 byte default algorithm id, one byte
1007ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // default IV size, 16 bytes default KeyID
1008ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // (ISO 23001-7)
1009ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            char buf[4];
1010ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memset(buf, 0, 4);
1011ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 4, buf + 1, 3) < 3) {
1012ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1013ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1014ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t defaultAlgorithmId = ntohl(*((int32_t*)buf));
1015ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (defaultAlgorithmId > 1) {
1016ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only 0 (clear) and 1 (AES-128) are valid
1017ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1018ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1019ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1020ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memset(buf, 0, 4);
1021ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 7, buf + 3, 1) < 1) {
1022ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1023ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1024ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t defaultIVSize = ntohl(*((int32_t*)buf));
1025ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1026ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((defaultAlgorithmId == 0 && defaultIVSize != 0) ||
1027ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    (defaultAlgorithmId != 0 && defaultIVSize == 0)) {
1028ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only unencrypted data must have 0 IV size
1029ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1030ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            } else if (defaultIVSize != 0 &&
1031ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    defaultIVSize != 8 &&
1032ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    defaultIVSize != 16) {
1033ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only supported sizes are 0, 8 and 16
1034ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1035ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1036ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1037ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint8_t defaultKeyId[16];
1038ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1039ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 8, &defaultKeyId, 16) < 16) {
1040ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1041ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1042ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1043ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setInt32(kKeyCryptoMode, defaultAlgorithmId);
1044ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setInt32(kKeyCryptoDefaultIVSize, defaultIVSize);
1045ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setData(kKeyCryptoKey, 'tenc', defaultKeyId, 16);
1046ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
1047ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1048ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1049ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
105020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'k', 'h', 'd'):
105120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1052ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            status_t err;
1053ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) {
1054ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber                return err;
105520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
105620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
105720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
105820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
105920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
106020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1061ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('p', 's', 's', 'h'):
1062ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
1063ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            PsshInfo pssh;
1064ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1065ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 4, &pssh.uuid, 16) < 16) {
1066ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1067ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1068ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1069ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t psshdatalen = 0;
1070ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 20, &psshdatalen, 4) < 4) {
1071ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1072ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1073ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            pssh.datalen = ntohl(psshdatalen);
1074ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("pssh data size: %d", pssh.datalen);
1075ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (pssh.datalen + 20 > chunk_size) {
1076ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // pssh data length exceeds size of containing box
1077ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1078ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1079ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1080ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            pssh.data = new uint8_t[pssh.datalen];
1081ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("allocated pssh @ %p", pssh.data);
1082ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ssize_t requested = (ssize_t) pssh.datalen;
1083ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 24, pssh.data, requested) < requested) {
1084ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1085ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1086ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mPssh.push_back(pssh);
1087ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1088ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
1089ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1090ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1091ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
109220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'h', 'd'):
109320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
109420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
109520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
109620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
109720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
109820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t version;
109934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
110020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, &version, sizeof(version))
110120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(version)) {
110220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
110320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
110420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1105c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t timescale_offset;
110620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
110720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
110820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 16;
110920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else if (version == 0) {
111020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 8;
111120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
111220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
111320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
111420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
111520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t timescale;
111634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
111720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        timescale_offset, &timescale, sizeof(timescale))
111820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(timescale)) {
111920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
112020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
112120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
112220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->timescale = ntohl(timescale);
112320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
112405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            int64_t duration = 0;
112520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
112634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
112720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration, sizeof(duration))
112820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration)) {
112920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
113020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
113120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = ntoh64(duration);
113220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
113305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t duration32;
113434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
113520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration32, sizeof(duration32))
113620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration32)) {
113720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
113820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
113905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // ffmpeg sets duration to -1, which is incorrect.
114005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (duration32 != 0xffffffff) {
114105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    duration = ntohl(duration32);
114205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
114320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
114448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mLastTrack->meta->setInt64(
114548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                    kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
114620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11477a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            uint8_t lang[2];
11487a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            off64_t lang_offset;
11497a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            if (version == 1) {
11507a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                lang_offset = timescale_offset + 4 + 8;
11517a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            } else if (version == 0) {
11527a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                lang_offset = timescale_offset + 4 + 4;
11537a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            } else {
11547a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                return ERROR_IO;
11557a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            }
11567a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
11577a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            if (mDataSource->readAt(lang_offset, &lang, sizeof(lang))
11587a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                    < (ssize_t)sizeof(lang)) {
11597a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                return ERROR_IO;
11607a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            }
11617a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
11627a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // To get the ISO-639-2/T three character language code
11637a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // 1 bit pad followed by 3 5-bits characters. Each character
11647a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // is packed as the difference between its ASCII value and 0x60.
11657a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            char lang_code[4];
11667a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[0] = ((lang[0] >> 2) & 0x1f) + 0x60;
11677a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[1] = ((lang[0] & 0x3) << 3 | (lang[1] >> 5)) + 0x60;
11687a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[2] = (lang[1] & 0x1f) + 0x60;
11697a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[3] = '\0';
11707a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
11717a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            mLastTrack->meta->setCString(
11727a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                    kKeyMediaLanguage, lang_code);
11737a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
117420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
117520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
117620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
117720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
117820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'd'):
117920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 8) {
118120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
118220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
118320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
118420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8];
1185c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size < (off64_t)sizeof(buffer)) {
1186bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1187bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
1188bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
118934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
119020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, 8) < 8) {
119120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
119220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
119320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
119420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
119520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
119620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
119720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
119820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
119920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t entry_count = U32_AT(&buffer[4]);
120020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
120120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (entry_count > 1) {
12023b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // For 3GPP timed text, there could be multiple tx3g boxes contain
12033b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // multiple text display formats. These formats will be used to
12043b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // display the timed text.
1205ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // For encrypted files, there may also be more than one entry.
12063b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                const char *mime;
12073b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1208ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) &&
1209ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                        strcasecmp(mime, "application/octet-stream")) {
12103b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    // For now we only support a single type of media per track.
12113b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    mLastTrack->skipTrack = true;
12123b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    *offset += chunk_size;
12133b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    break;
12143b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                }
121520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1216c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
121720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + 8;
121820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            for (uint32_t i = 0; i < entry_count; ++i) {
121920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
122020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
122120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
122220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
122320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1224bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1225bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1226bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1227bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
122820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
122920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
123020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
123120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
123248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        case FOURCC('e', 'n', 'c', 'a'):
123320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
1234371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
123520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
123620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8 + 20];
123720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
123820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic AudioSampleEntry size.
123920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
124020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
124120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
124234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
124320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
124420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
124520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
124620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
124720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
124848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t num_channels = U16_AT(&buffer[16]);
124920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
125081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint16_t sample_size = U16_AT(&buffer[18]);
125181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
125281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
125348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (chunk_type != FOURCC('e', 'n', 'c', 'a')) {
125448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                // if the chunk type is enca, we'll get the type from the sinf/frma box later
125548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
125648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate);
125720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
125848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            ALOGV("*** coding='%s' %d channels, size %d, rate %d\n",
125981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                   chunk, num_channels, sample_size, sample_rate);
126020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
126120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
126220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1263c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
126420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
126520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
126620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
126720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
126820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
126920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
127020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1271bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1272bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1273bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1274bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
127520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
127620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
127720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
127820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
1279ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('e', 'n', 'c', 'v'):
128020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
1281e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('H', '2', '6', '3'):
1282e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('h', '2', '6', '3'):
128320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
128420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
12857be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber            mHasVideo = true;
12867be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
128720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[78];
128820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
128920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic VideoSampleEntry size.
129020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
129120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
129220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
129334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
129420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
129520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
129620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
129720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
129820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
129920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t width = U16_AT(&buffer[6 + 18]);
130020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t height = U16_AT(&buffer[6 + 20]);
130120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1302ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // The video sample is not standard-compliant if it has invalid dimension.
1303a6256238d9015c42129fe43791968768fe501efaJames Dong            // Use some default width and height value, and
1304a6256238d9015c42129fe43791968768fe501efaJames Dong            // let the decoder figure out the actual width and height (and thus
1305a6256238d9015c42129fe43791968768fe501efaJames Dong            // be prepared for INFO_FOMRAT_CHANGED event).
1306a6256238d9015c42129fe43791968768fe501efaJames Dong            if (width == 0)  width  = 352;
1307a6256238d9015c42129fe43791968768fe501efaJames Dong            if (height == 0) height = 288;
1308a6256238d9015c42129fe43791968768fe501efaJames Dong
1309134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            // printf("*** coding='%s' width=%d height=%d\n",
1310134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            //        chunk, width, height);
131120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1312ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (chunk_type != FOURCC('e', 'n', 'c', 'v')) {
1313ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // if the chunk type is encv, we'll get the type from the sinf/frma box later
1314ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
1315ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
131620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyWidth, width);
131720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyHeight, height);
131820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1319c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
132020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
132120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
132220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
132320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
132420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
132520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
132620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1327bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1328bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1329bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1330bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
133120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
133220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
133320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
133420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'c', 'o'):
133520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('c', 'o', '6', '4'):
133620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
133720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
133820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setChunkOffsetParams(
133920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
134020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
134120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
134220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
134320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
134420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
134520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
134620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
134720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
134820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
134920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'c'):
135020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
135120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
135220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleToChunkParams(
135320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
135420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
135520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
135720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
135820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
135920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
136020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
136120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
136220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
136320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'z'):
136420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'z', '2'):
136520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
136620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
136720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleSizeParams(
136820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
136920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
137020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
137120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
137220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
137320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1374738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            size_t max_size;
137549110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            err = mLastTrack->sampleTable->getMaxSampleSize(&max_size);
137649110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber
137749110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            if (err != OK) {
137849110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber                return err;
137949110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            }
1380738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber
138105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (max_size != 0) {
138205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // Assume that a given buffer only contains at most 10 chunks,
138305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // each chunk originally prefixed with a 2 byte length will
138405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
138505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // and thus will grow by 2 bytes per chunk.
1386e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                if (max_size > SIZE_MAX - 10 * 2) {
1387e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                    ALOGE("max sample size too big: %zu", max_size);
1388e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                    return ERROR_MALFORMED;
1389e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                }
139005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
139105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            } else {
139205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // No size was specified. Pick a conservatively large size.
1393e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                uint32_t width, height;
1394e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                if (!mLastTrack->meta->findInt32(kKeyWidth, (int32_t*)&width) ||
1395e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                    !mLastTrack->meta->findInt32(kKeyHeight,(int32_t*) &height)) {
139605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ALOGE("No width or height, assuming worst case 1080p");
1397f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    width = 1920;
1398f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    height = 1080;
1399e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                } else {
1400e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                    // A resolution was specified, check that it's not too big. The values below
1401e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                    // were chosen so that the calculations below don't cause overflows, they're
1402e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                    // not indicating that resolutions up to 32kx32k are actually supported.
1403e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                    if (width > 32768 || height > 32768) {
1404e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                        ALOGE("can't support %u x %u video", width, height);
1405e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                        return ERROR_MALFORMED;
1406e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen                    }
140705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
1408f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar
14094256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen                const char *mime;
14104256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1411f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
1412f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // AVC requires compression ratio of at least 2, and uses
1413f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // macroblocks
1414f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    max_size = ((width + 15) / 16) * ((height + 15) / 16) * 192;
1415f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                } else {
1416f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // For all other formats there is no minimum compression
1417f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // ratio. Use compression ratio of 1.
1418f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    max_size = width * height * 3 / 2;
1419f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                }
1420f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size);
142105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
142220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
1423113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong
14244256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            // NOTE: setting another piece of metadata invalidates any pointers (such as the
14254256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            // mimetype) previously obtained, so don't cache them.
14264256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            const char *mime;
14274256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1428113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            // Calculate average frame rate.
1429113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            if (!strncasecmp("video/", mime, 6)) {
1430113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                size_t nSamples = mLastTrack->sampleTable->countSamples();
1431113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                int64_t durationUs;
1432113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                if (mLastTrack->meta->findInt64(kKeyDuration, &durationUs)) {
1433113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                    if (durationUs > 0) {
1434113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                        int32_t frameRate = (nSamples * 1000000LL +
1435113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                                    (durationUs >> 1)) / durationUs;
1436113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                        mLastTrack->meta->setInt32(kKeyFrameRate, frameRate);
1437113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                    }
1438113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                }
1439113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            }
1440113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong
144120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
144220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
144320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
144420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 't', 's'):
144520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
144620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
144720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setTimeToSampleParams(
144820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
144920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
145020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
145120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
145220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
145320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
145420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
145520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
145620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
145720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14584931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        case FOURCC('c', 't', 't', 's'):
14594931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        {
14604931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            status_t err =
14614931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                mLastTrack->sampleTable->setCompositionTimeToSampleParams(
14624931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                        data_offset, chunk_data_size);
14634931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
14644931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            if (err != OK) {
14654931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                return err;
14664931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            }
14674931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
14684931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            *offset += chunk_size;
14694931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            break;
14704931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        }
14714931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
147220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 's'):
147320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
147420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
147520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSyncSampleParams(
147620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
147720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
147820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
147920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
148020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
148120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
148220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
148320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
148420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
148520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14864948818cb91176df74c972ac27b2f392b5d148bcJames Dong        // @xyz
14874948818cb91176df74c972ac27b2f392b5d148bcJames Dong        case FOURCC('\xA9', 'x', 'y', 'z'):
14884948818cb91176df74c972ac27b2f392b5d148bcJames Dong        {
14894948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Best case the total data length inside "@xyz" box
14904948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // would be 8, for instance "@xyz" + "\x00\x04\x15\xc7" + "0+0/",
14914948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // where "\x00\x04" is the text string length with value = 4,
14924948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // "\0x15\xc7" is the language code = en, and "0+0" is a
14934948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // location (string) value with longitude = 0 and latitude = 0.
14944948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (chunk_data_size < 8) {
14954948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_MALFORMED;
14964948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
14974948818cb91176df74c972ac27b2f392b5d148bcJames Dong
14984948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Worst case the location string length would be 18,
14994948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // for instance +90.0000-180.0000, without the trailing "/" and
15004948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // the string length + language code.
15014948818cb91176df74c972ac27b2f392b5d148bcJames Dong            char buffer[18];
15024948818cb91176df74c972ac27b2f392b5d148bcJames Dong
15034948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Substracting 5 from the data size is because the text string length +
15044948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // language code takes 4 bytes, and the trailing slash "/" takes 1 byte.
15054948818cb91176df74c972ac27b2f392b5d148bcJames Dong            off64_t location_length = chunk_data_size - 5;
15064948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (location_length >= (off64_t) sizeof(buffer)) {
15074948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_MALFORMED;
15084948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
15094948818cb91176df74c972ac27b2f392b5d148bcJames Dong
15104948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (mDataSource->readAt(
15114948818cb91176df74c972ac27b2f392b5d148bcJames Dong                        data_offset + 4, buffer, location_length) < location_length) {
15124948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_IO;
15134948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
15144948818cb91176df74c972ac27b2f392b5d148bcJames Dong
15154948818cb91176df74c972ac27b2f392b5d148bcJames Dong            buffer[location_length] = '\0';
15164948818cb91176df74c972ac27b2f392b5d148bcJames Dong            mFileMetaData->setCString(kKeyLocation, buffer);
15174948818cb91176df74c972ac27b2f392b5d148bcJames Dong            *offset += chunk_size;
15184948818cb91176df74c972ac27b2f392b5d148bcJames Dong            break;
15194948818cb91176df74c972ac27b2f392b5d148bcJames Dong        }
15204948818cb91176df74c972ac27b2f392b5d148bcJames Dong
152120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('e', 's', 'd', 's'):
152220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
152320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
152420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
152520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
152620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
152720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[256];
1528c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size > (off64_t)sizeof(buffer)) {
152920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
153020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
153120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
153234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
153320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
153420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
153520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
153620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
153720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
153820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
153920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
154020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
154120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
154220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
154320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
154420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1545ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            if (mPath.size() >= 2
1546ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
1547ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // Information from the ESDS must be relied on for proper
1548ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // setup of sample rate and channel count for MPEG4 Audio.
1549ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // The generic header appears to only contain generic
1550ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // information...
1551ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1552ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio(
1553ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                        &buffer[4], chunk_data_size - 4);
1554ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1555ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                if (err != OK) {
1556ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    return err;
1557ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                }
1558ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            }
1559ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
156020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
156120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
156220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
156320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
156420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', 'C'):
156520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1566d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson            sp<ABuffer> buffer = new ABuffer(chunk_data_size);
156720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
156834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
1569d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson                        data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
157020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
157120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
157220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
157320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
1574d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson                    kKeyAVCC, kTypeAVCC, buffer->data(), chunk_data_size);
157520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
157620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
157720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
157820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
157920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1580244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        case FOURCC('d', '2', '6', '3'):
1581244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        {
158217e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            /*
158317e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * d263 contains a fixed 7 bytes part:
158417e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   vendor - 4 bytes
158517e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   version - 1 byte
158617e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   level - 1 byte
158717e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   profile - 1 byte
158817e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * optionally, "d263" box itself may contain a 16-byte
158917e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * bit rate box (bitr)
159017e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   average bit rate - 4 bytes
159117e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   max bit rate - 4 bytes
159217e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             */
159317e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            char buffer[23];
159417e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            if (chunk_data_size != 7 &&
159517e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong                chunk_data_size != 23) {
159629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Incorrect D263 box size %lld", chunk_data_size);
1597244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                return ERROR_MALFORMED;
1598244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            }
1599244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1600244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            if (mDataSource->readAt(
1601244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                    data_offset, buffer, chunk_data_size) < chunk_data_size) {
1602244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                return ERROR_IO;
1603244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            }
1604244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1605244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size);
1606244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1607244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            *offset += chunk_size;
1608244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            break;
1609244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        }
1610244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
161172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'e', 't', 'a'):
161272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
161372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            uint8_t buffer[4];
1614c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size < (off64_t)sizeof(buffer)) {
1615bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1616bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
1617bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
161872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
161972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, buffer, 4) < 4) {
162072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
162172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
162272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
162372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (U32_AT(buffer) != 0) {
162472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                // Should be version 0, flags 0.
1625ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
1626ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // If it's not, let's assume this is one of those
1627ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // apparently malformed chunks that don't have flags
1628ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // and completely different semantics than what's
1629ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // in the MPEG4 specs and skip it.
1630ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                *offset += chunk_size;
1631ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                return OK;
163272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
163372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1634c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
163572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset = data_offset + sizeof(buffer);
163672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            while (*offset < stop_offset) {
163772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                status_t err = parseChunk(offset, depth + 1);
163872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
163972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
164072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
164172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
1642bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1643bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1644bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1645bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
164672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
164772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
164872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
16495d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('m', 'e', 'a', 'n'):
16505d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('n', 'a', 'm', 'e'):
165172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('d', 'a', 't', 'a'):
165272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
165372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mPath.size() == 6 && underMetaDataPath(mPath)) {
165472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                status_t err = parseMetaData(data_offset, chunk_data_size);
165572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
165672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
165772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
165872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
165972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
166072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
166172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset += chunk_size;
166272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
166372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
166472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
166572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'v', 'h', 'd'):
166672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
1667fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            if (chunk_data_size < 24) {
166872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_MALFORMED;
166972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
167072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1671fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            uint8_t header[24];
167272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
167372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, header, sizeof(header))
167472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    < (ssize_t)sizeof(header)) {
167572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
167672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
167772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1678fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            uint64_t creationTime;
167972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (header[0] == 1) {
168072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U64_AT(&header[4]);
1681fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                mHeaderTimescale = U32_AT(&header[20]);
1682bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (header[0] != 0) {
1683bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
168472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            } else {
168572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U32_AT(&header[4]);
1686fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                mHeaderTimescale = U32_AT(&header[12]);
168772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
168872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
168972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            String8 s;
169072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            convertTimeToDate(creationTime, &s);
169172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
169272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(kKeyDate, s.string());
169372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
169472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset += chunk_size;
169572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
169672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
169772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1698dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        case FOURCC('m', 'd', 'a', 't'):
1699dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        {
1700ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("mdat chunk, drm: %d", mIsDrm);
1701dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (!mIsDrm) {
1702dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                *offset += chunk_size;
1703dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                break;
1704dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
1705dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
1706dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (chunk_size < 8) {
1707dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
1708dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
1709dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
1710dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return parseDrmSINF(offset, data_offset);
1711dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
1712dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
17133b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        case FOURCC('h', 'd', 'l', 'r'):
17143b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        {
17153b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t buffer;
17163b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (mDataSource->readAt(
17173b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                        data_offset + 8, &buffer, 4) < 4) {
17183b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_IO;
17193b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17203b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17213b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type = ntohl(buffer);
17223b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            // For the 3GPP file format, the handler-type within the 'hdlr' box
1723e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            // shall be 'text'. We also want to support 'sbtl' handler type
1724e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            // for a practical reason as various MPEG4 containers use it.
1725e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            if (type == FOURCC('t', 'e', 'x', 't') || type == FOURCC('s', 'b', 't', 'l')) {
17263b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
17273b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17283b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17293b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            *offset += chunk_size;
17303b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            break;
17313b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        }
17323b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17337a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        case FOURCC('t', 'x', '3', 'g'):
17347a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        {
17353b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type;
17363b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            const void *data;
17373b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            size_t size = 0;
17383b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (!mLastTrack->meta->findData(
17393b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    kKeyTextFormatData, &type, &data, &size)) {
17403b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                size = 0;
17413b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17423b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17430e20b2093aa2bbc93afed8d68d3765d18a431b74Nick Kralevich            if ((chunk_size > SIZE_MAX) || (SIZE_MAX - chunk_size <= size)) {
1744e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake                return ERROR_MALFORMED;
1745e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake            }
1746e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake
17473b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint8_t *buffer = new uint8_t[size + chunk_size];
1748e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake            if (buffer == NULL) {
1749e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake                return ERROR_MALFORMED;
1750e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake            }
17513b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17523b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (size > 0) {
17533b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                memcpy(buffer, data, size);
17543b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17553b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17563b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size))
17573b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    < chunk_size) {
17583b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                delete[] buffer;
17593b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                buffer = NULL;
17603b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17613b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_IO;
17623b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17633b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17643b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            mLastTrack->meta->setData(
17653b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    kKeyTextFormatData, 0, buffer, size + chunk_size);
17663b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17673b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            delete[] buffer;
17687a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
17697a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            *offset += chunk_size;
17707a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            break;
17717a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        }
17727a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
1773515e855eae78aa495da58356486aaa666cb57fd1James Dong        case FOURCC('c', 'o', 'v', 'r'):
1774515e855eae78aa495da58356486aaa666cb57fd1James Dong        {
1775515e855eae78aa495da58356486aaa666cb57fd1James Dong            if (mFileMetaData != NULL) {
17763856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("chunk_data_size = %lld and data_offset = %lld",
1777515e855eae78aa495da58356486aaa666cb57fd1James Dong                        chunk_data_size, data_offset);
177805ddc499b9d50c90f552ed1333110f28a1406e7cJoshua J. Drake
17797e9ac3509d72e8dc6f1316b5ce0a0066638b9737Dan Albert                if (chunk_data_size < 0 || static_cast<uint64_t>(chunk_data_size) >= SIZE_MAX - 1) {
178005ddc499b9d50c90f552ed1333110f28a1406e7cJoshua J. Drake                    return ERROR_MALFORMED;
178105ddc499b9d50c90f552ed1333110f28a1406e7cJoshua J. Drake                }
17821552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1);
1783515e855eae78aa495da58356486aaa666cb57fd1James Dong                if (mDataSource->readAt(
17841552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                    data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) {
1785515e855eae78aa495da58356486aaa666cb57fd1James Dong                    return ERROR_IO;
1786515e855eae78aa495da58356486aaa666cb57fd1James Dong                }
1787515e855eae78aa495da58356486aaa666cb57fd1James Dong                const int kSkipBytesOfDataBox = 16;
17884a492bf2ac47b9844d2527e1fcdf0064c3d8d52eJoshua J. Drake                if (chunk_data_size <= kSkipBytesOfDataBox) {
17894a492bf2ac47b9844d2527e1fcdf0064c3d8d52eJoshua J. Drake                    return ERROR_MALFORMED;
17904a492bf2ac47b9844d2527e1fcdf0064c3d8d52eJoshua J. Drake                }
17914a492bf2ac47b9844d2527e1fcdf0064c3d8d52eJoshua J. Drake
1792515e855eae78aa495da58356486aaa666cb57fd1James Dong                mFileMetaData->setData(
1793515e855eae78aa495da58356486aaa666cb57fd1James Dong                    kKeyAlbumArt, MetaData::TYPE_NONE,
17941552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                    buffer->data() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox);
1795515e855eae78aa495da58356486aaa666cb57fd1James Dong            }
1796515e855eae78aa495da58356486aaa666cb57fd1James Dong
1797515e855eae78aa495da58356486aaa666cb57fd1James Dong            *offset += chunk_size;
1798515e855eae78aa495da58356486aaa666cb57fd1James Dong            break;
1799515e855eae78aa495da58356486aaa666cb57fd1James Dong        }
1800515e855eae78aa495da58356486aaa666cb57fd1James Dong
18015d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('-', '-', '-', '-'):
18025d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        {
18035d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentMean.clear();
18045d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentName.clear();
18055d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentData.clear();
18065d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            *offset += chunk_size;
18075d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            break;
18085d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        }
18095d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen
181005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('s', 'i', 'd', 'x'):
181105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        {
181205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            parseSegmentIndex(data_offset, chunk_data_size);
181305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset += chunk_size;
181405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return UNKNOWN_ERROR; // stop parsing after sidx
181505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
181605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
181720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
181820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
181920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
182020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
182120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
182220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
182320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
182420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
182520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
182620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
182705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) {
182805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen  ALOGV("MPEG4Extractor::parseSegmentIndex");
182905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
183005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 12) {
183105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      return -EINVAL;
183205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
183305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
183405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
183505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) {
183605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
183705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
183805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
183905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t version = flags >> 24;
184005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    flags &= 0xffffff;
184105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
184205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx version %d", version);
184305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
184405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t referenceId;
184505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, &referenceId)) {
184605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
184705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
184805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
184905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t timeScale;
185005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 8, &timeScale)) {
185105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
185205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
185305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx refid/timescale: %d/%d", referenceId, timeScale);
185405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
185505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t earliestPresentationTime;
185605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t firstOffset;
185705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
185805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 12;
185905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 12;
186005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
186105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (version == 0) {
186205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 8) {
186305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
186405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
186505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t tmp;
186605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
186705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
186805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
186905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        earliestPresentationTime = tmp;
187005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset + 4, &tmp)) {
187105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
187205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
187305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        firstOffset = tmp;
187405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 8;
187505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 8;
187605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
187705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 16) {
187805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
187905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
188005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset, &earliestPresentationTime)) {
188105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
188205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
188305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset + 8, &firstOffset)) {
188405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
188505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
188605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 16;
188705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 16;
188805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
188905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx pres/off: %Ld/%Ld", earliestPresentationTime, firstOffset);
189005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
189105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 4) {
189205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
189305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
189405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
189505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint16_t referenceCount;
189605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt16(offset + 2, &referenceCount)) {
189705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
189805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
189905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 4;
190005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 4;
190105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("refcount: %d", referenceCount);
190205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
190305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < referenceCount * 12) {
190405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
190505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
190605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
190705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t total_duration = 0;
190805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    for (unsigned int i = 0; i < referenceCount; i++) {
190905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t d1, d2, d3;
191005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
191105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &d1) ||     // size
191205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            !mDataSource->getUInt32(offset + 4, &d2) || // duration
191305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            !mDataSource->getUInt32(offset + 8, &d3)) { // flags
191405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
191505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
191605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
191705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (d1 & 0x80000000) {
191805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGW("sub-sidx boxes not supported yet");
191905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
192005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool sap = d3 & 0x80000000;
192105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool saptype = d3 >> 28;
192205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!sap || saptype > 2) {
192305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGW("not a stream access point, or unsupported type");
192405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
192505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        total_duration += d2;
192605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 12;
192705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV(" item %d, %08x %08x %08x", i, d1, d2, d3);
192805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        SidxEntry se;
192905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        se.mSize = d1 & 0x7fffffff;
193005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        se.mDurationUs = 1000000LL * d2 / timeScale;
193105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mSidxEntries.add(se);
193205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
193305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
193405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mSidxDuration = total_duration * 1000000 / timeScale;
193505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("duration: %lld", mSidxDuration);
193605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
193705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t metaDuration;
193805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mLastTrack->meta->findInt64(kKeyDuration, &metaDuration) || metaDuration == 0) {
193905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mLastTrack->meta->setInt64(kKeyDuration, mSidxDuration);
194005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
194105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
194205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
194305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
194405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
194505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
1946ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huberstatus_t MPEG4Extractor::parseTrackHeader(
1947c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t data_offset, off64_t data_size) {
1948ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (data_size < 4) {
1949ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_MALFORMED;
1950ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1951ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1952ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint8_t version;
1953ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (mDataSource->readAt(data_offset, &version, 1) < 1) {
1954ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_IO;
1955ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1956ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1957ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    size_t dynSize = (version == 1) ? 36 : 24;
1958ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1959ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint8_t buffer[36 + 60];
1960ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1961c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    if (data_size != (off64_t)dynSize + 60) {
1962ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_MALFORMED;
1963ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1964ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1965ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (mDataSource->readAt(
1966ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber                data_offset, buffer, data_size) < (ssize_t)data_size) {
1967ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_IO;
1968ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1969ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1970ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint64_t ctime, mtime, duration;
1971ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t id;
1972ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1973ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (version == 1) {
1974ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        ctime = U64_AT(&buffer[4]);
1975ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mtime = U64_AT(&buffer[12]);
1976ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        id = U32_AT(&buffer[20]);
1977ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        duration = U64_AT(&buffer[28]);
197804022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen    } else if (version == 0) {
1979ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        ctime = U32_AT(&buffer[4]);
1980ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mtime = U32_AT(&buffer[8]);
1981ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        id = U32_AT(&buffer[12]);
1982ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        duration = U32_AT(&buffer[20]);
198304022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen    } else {
198404022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen        return ERROR_UNSUPPORTED;
1985ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1986ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1987ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    mLastTrack->meta->setInt32(kKeyTrackID, id);
1988ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1989ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    size_t matrixOffset = dynSize + 16;
1990ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a00 = U32_AT(&buffer[matrixOffset]);
1991ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a01 = U32_AT(&buffer[matrixOffset + 4]);
1992ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t dx = U32_AT(&buffer[matrixOffset + 8]);
1993ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a10 = U32_AT(&buffer[matrixOffset + 12]);
1994ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a11 = U32_AT(&buffer[matrixOffset + 16]);
1995ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t dy = U32_AT(&buffer[matrixOffset + 20]);
1996ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1997ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#if 0
1998df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("x' = %.2f * x + %.2f * y + %.2f",
1999ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber         a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f);
2000df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("y' = %.2f * x + %.2f * y + %.2f",
2001ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber         a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f);
2002ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#endif
2003ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2004ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t rotationDegrees;
2005ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2006ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    static const int32_t kFixedOne = 0x10000;
2007ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) {
2008ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        // Identity, no rotation
2009ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 0;
2010ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) {
2011ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 90;
2012ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) {
2013ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 270;
2014ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) {
2015ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 180;
2016ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else {
20175ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("We only support 0,90,180,270 degree rotation matrices");
2018ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 0;
2019ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2020ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2021ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (rotationDegrees != 0) {
2022ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees);
2023ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2024ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2025b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    // Handle presentation display size, which could be different
2026b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    // from the image size indicated by kKeyWidth and kKeyHeight.
2027ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t width = U32_AT(&buffer[dynSize + 52]);
2028ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t height = U32_AT(&buffer[dynSize + 56]);
2029b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    mLastTrack->meta->setInt32(kKeyDisplayWidth, width >> 16);
2030b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    mLastTrack->meta->setInt32(kKeyDisplayHeight, height >> 16);
2031ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2032ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    return OK;
2033ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber}
2034ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2035c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseMetaData(off64_t offset, size_t size) {
2036a1e21653e86d21a4ab0946ee2761b6f0163d5742Nick Kralevich    if (size < 4 || size == SIZE_MAX) {
203772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_MALFORMED;
203872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
203972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
204072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint8_t *buffer = new uint8_t[size + 1];
204172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (mDataSource->readAt(
204272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                offset, buffer, size) != (ssize_t)size) {
204372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        delete[] buffer;
204472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        buffer = NULL;
204572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
204672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_IO;
204772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
204872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
204972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t flags = U32_AT(buffer);
205072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
205172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t metadataKey = 0;
20525d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    char chunk[5];
20535d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    MakeFourCCString(mPath[4], chunk);
20545d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    ALOGV("meta: %s @ %lld", chunk, offset);
205572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    switch (mPath[4]) {
205672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'a', 'l', 'b'):
205772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
205872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbum;
205972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
206072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
206172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'A', 'R', 'T'):
206272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
206372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyArtist;
206472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
206572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
206666ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        case FOURCC('a', 'A', 'R', 'T'):
206766ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        {
206866ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            metadataKey = kKeyAlbumArtist;
206966ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            break;
207066ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        }
207172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'd', 'a', 'y'):
207272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
207372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyYear;
207472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
207572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
207672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'n', 'a', 'm'):
207772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
207872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyTitle;
207972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
208072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
208172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'w', 'r', 't'):
208272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
208372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyWriter;
208472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
208572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
208672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('c', 'o', 'v', 'r'):
208772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
208872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbumArt;
208972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
209072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
209172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('g', 'n', 'r', 'e'):
209272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
209372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyGenre;
209472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
209572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
209626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC(0xa9, 'g', 'e', 'n'):
209726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
209826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            metadataKey = kKeyGenre;
209926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
210026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
210111f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        case FOURCC('c', 'p', 'i', 'l'):
210211f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        {
210311f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            if (size == 9 && flags == 21) {
210411f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                char tmp[16];
210511f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                sprintf(tmp, "%d",
210611f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                        (int)buffer[size - 1]);
210711f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen
210811f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                mFileMetaData->setCString(kKeyCompilation, tmp);
210911f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            }
211011f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            break;
211111f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        }
211272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('t', 'r', 'k', 'n'):
211372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
211472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (size == 16 && flags == 0) {
211572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char tmp[16];
2116afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTrack = (uint16_t*)&buffer[10];
2117afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTotalTracks = (uint16_t*)&buffer[12];
2118afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                sprintf(tmp, "%d/%d", ntohs(*pTrack), ntohs(*pTotalTracks));
211972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
212072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
212172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
212272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
212372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
212426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC('d', 'i', 's', 'k'):
212526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
2126afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik            if ((size == 14 || size == 16) && flags == 0) {
212726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                char tmp[16];
2128afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pDisc = (uint16_t*)&buffer[10];
2129afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTotalDiscs = (uint16_t*)&buffer[12];
2130afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                sprintf(tmp, "%d/%d", ntohs(*pDisc), ntohs(*pTotalDiscs));
213126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
213226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(kKeyDiscNumber, tmp);
213326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            }
213426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
213526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
21365d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('-', '-', '-', '-'):
21375d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        {
21385d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            buffer[size] = '\0';
21395d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            switch (mPath[5]) {
21405d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('m', 'e', 'a', 'n'):
21415d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentMean.setTo((const char *)buffer + 4);
21425d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
21435d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('n', 'a', 'm', 'e'):
21445d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentName.setTo((const char *)buffer + 4);
21455d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
21465d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('d', 'a', 't', 'a'):
21475d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentData.setTo((const char *)buffer + 8);
21485d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
21495d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            }
21508c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
21518c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // Once we have a set of mean/name/data info, go ahead and process
21528c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // it to see if its something we are interested in.  Whether or not
21538c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // were are interested in the specific tag, make sure to clear out
21548c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // the set so we can be ready to process another tuple should one
21558c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // show up later in the file.
21568c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            if ((mLastCommentMean.length() != 0) &&
21578c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                (mLastCommentName.length() != 0) &&
21588c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                (mLastCommentData.length() != 0)) {
21598c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
21608c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                if (mLastCommentMean == "com.apple.iTunes"
21618c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        && mLastCommentName == "iTunSMPB") {
21628c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    int32_t delay, padding;
21638c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    if (sscanf(mLastCommentData,
21648c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                               " %*x %x %x %*x", &delay, &padding) == 2) {
21658c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
21668c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        mLastTrack->meta->setInt32(kKeyEncoderPadding, padding);
21678c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    }
21685d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                }
21698c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
21705d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentMean.clear();
21715d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentName.clear();
21725d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentData.clear();
21735d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            }
21745d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            break;
21755d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        }
217626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
217772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        default:
217872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
217972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
218072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
218172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (size >= 8 && metadataKey) {
218272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        if (metadataKey == kKeyAlbumArt) {
218372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setData(
218472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    kKeyAlbumArt, MetaData::TYPE_NONE,
218572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    buffer + 8, size - 8);
218672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else if (metadataKey == kKeyGenre) {
218772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (flags == 0) {
218826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // uint8_t genre code, iTunes genre codes are
218926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // the standard id3 codes, except they start
219026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // at 1 instead of 0 (e.g. Pop is 14, not 13)
219126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // We use standard id3 numbering, so subtract 1.
219226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                int genrecode = (int)buffer[size - 1];
219326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                genrecode--;
219426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                if (genrecode < 0) {
219526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                    genrecode = 255; // reserved for 'unknown genre'
219626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                }
219772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char genre[10];
219826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                sprintf(genre, "%d", genrecode);
219972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
220072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(metadataKey, genre);
220126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            } else if (flags == 1) {
220226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // custom genre string
220326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                buffer[size] = '\0';
220426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
220526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(
220626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                        metadataKey, (const char *)buffer + 8);
220772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
220872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else {
220972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            buffer[size] = '\0';
221072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
221172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(
221272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    metadataKey, (const char *)buffer + 8);
221372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
221472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
221572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
221672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    delete[] buffer;
221772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    buffer = NULL;
221872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
221972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return OK;
222072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
222172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
2222693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
222320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
222420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
2225693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return NULL;
222620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
222720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
222820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
222920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
223020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
2231693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber            return NULL;
223220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
223320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
223420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
223520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
223620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
223720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2238371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
2239371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
2240371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
2241371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
2242ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("getTrack called, pssh: %d", mPssh.size());
2243ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2244693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    return new MPEG4Source(
224505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            track->meta, mDataSource, track->timescale, track->sampleTable,
224605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mSidxEntries, mMoofOffset);
224720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
224820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2249bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber// static
2250bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) {
2251bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const char *mime;
2252bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    CHECK(track->meta->findCString(kKeyMIMEType, &mime));
2253bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2254bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    uint32_t type;
2255bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const void *data;
2256bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    size_t size;
2257bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
2258bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyAVCC, &type, &data, &size)
2259bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeAVCC) {
2260bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
2261bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
2262bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
2263bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
2264bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyESDS, &type, &data, &size)
2265bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeESDS) {
2266bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
2267bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
2268bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    }
2269bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2270169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber    if (!track->sampleTable->isValid()) {
2271169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        // Make sure we have all the metadata we need.
2272169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        return ERROR_MALFORMED;
2273169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber    }
2274169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber
2275bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    return OK;
2276bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber}
2277bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2278ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
2279ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        const void *esds_data, size_t esds_size) {
2280ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    ESDS esds(esds_data, esds_size);
228181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
228281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    uint8_t objectTypeIndication;
228381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
228481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return ERROR_MALFORMED;
228581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
228681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
228781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (objectTypeIndication == 0xe1) {
228881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        // This isn't MPEG4 audio at all, it's QCELP 14k...
228981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
229081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return OK;
229181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
229281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
2293633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong    if (objectTypeIndication  == 0x6b) {
2294633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // The media subtype is MP3 audio
2295633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // Our software MP3 audio decoder may not be able to handle
2296633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // packetized MP3 audio; for now, lets just return ERROR_UNSUPPORTED
229729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("MP3 track in MP4/3GPP file is not supported");
2298633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        return ERROR_UNSUPPORTED;
2299633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong    }
2300633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong
2301ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    const uint8_t *csd;
2302ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    size_t csd_size;
2303ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (esds.getCodecSpecificInfo(
2304ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                (const void **)&csd, &csd_size) != OK) {
2305ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
2306ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2307ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2308ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#if 0
2309ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    printf("ESD of size %d\n", csd_size);
2310ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    hexdump(csd, csd_size);
2311ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#endif
2312ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2313a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    if (csd_size == 0) {
2314a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // There's no further information, i.e. no codec specific data
2315a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // Let's assume that the information provided in the mpeg4 headers
2316a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // is accurate and hope for the best.
2317a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
2318a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        return OK;
2319a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    }
2320a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
2321ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (csd_size < 2) {
2322ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
2323ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2324ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
23253c836e7882e88de42e0e600627de433b61e78621Eric Laurent    static uint32_t kSamplingRate[] = {
23263c836e7882e88de42e0e600627de433b61e78621Eric Laurent        96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
23273c836e7882e88de42e0e600627de433b61e78621Eric Laurent        16000, 12000, 11025, 8000, 7350
23283c836e7882e88de42e0e600627de433b61e78621Eric Laurent    };
23293c836e7882e88de42e0e600627de433b61e78621Eric Laurent
2330aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    ABitReader br(csd, csd_size);
2331aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    uint32_t objectType = br.getBits(5);
2332ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2333aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    if (objectType == 31) {  // AAC-ELD => additional 6 bits
2334aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        objectType = 32 + br.getBits(6);
2335ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2336ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2337f590f948e6c0fe3c54008dd7802fd513f127792dEric Laurent    //keep AOT type
2338f590f948e6c0fe3c54008dd7802fd513f127792dEric Laurent    mLastTrack->meta->setInt32(kKeyAACAOT, objectType);
2339f590f948e6c0fe3c54008dd7802fd513f127792dEric Laurent
2340aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    uint32_t freqIndex = br.getBits(4);
2341aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
2342ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t sampleRate = 0;
2343ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t numChannels = 0;
2344ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (freqIndex == 15) {
2345ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        if (csd_size < 5) {
2346ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            return ERROR_MALFORMED;
2347ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
2348aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        sampleRate = br.getBits(24);
2349aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        numChannels = br.getBits(4);
2350ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    } else {
2351595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen        numChannels = br.getBits(4);
23523c836e7882e88de42e0e600627de433b61e78621Eric Laurent
23533c836e7882e88de42e0e600627de433b61e78621Eric Laurent        if (freqIndex == 13 || freqIndex == 14) {
23543c836e7882e88de42e0e600627de433b61e78621Eric Laurent            return ERROR_MALFORMED;
2355ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
2356ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
23573c836e7882e88de42e0e600627de433b61e78621Eric Laurent        sampleRate = kSamplingRate[freqIndex];
23583c836e7882e88de42e0e600627de433b61e78621Eric Laurent    }
2359595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen
23603c836e7882e88de42e0e600627de433b61e78621Eric Laurent    if (objectType == 5 || objectType == 29) { // SBR specific config per 14496-3 table 1.13
23613c836e7882e88de42e0e600627de433b61e78621Eric Laurent        uint32_t extFreqIndex = br.getBits(4);
23623c836e7882e88de42e0e600627de433b61e78621Eric Laurent        int32_t extSampleRate;
23633c836e7882e88de42e0e600627de433b61e78621Eric Laurent        if (extFreqIndex == 15) {
23643c836e7882e88de42e0e600627de433b61e78621Eric Laurent            if (csd_size < 8) {
2365595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen                return ERROR_MALFORMED;
2366595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen            }
23673c836e7882e88de42e0e600627de433b61e78621Eric Laurent            extSampleRate = br.getBits(24);
23683c836e7882e88de42e0e600627de433b61e78621Eric Laurent        } else {
23693c836e7882e88de42e0e600627de433b61e78621Eric Laurent            if (extFreqIndex == 13 || extFreqIndex == 14) {
23703c836e7882e88de42e0e600627de433b61e78621Eric Laurent                return ERROR_MALFORMED;
23713c836e7882e88de42e0e600627de433b61e78621Eric Laurent            }
23723c836e7882e88de42e0e600627de433b61e78621Eric Laurent            extSampleRate = kSamplingRate[extFreqIndex];
2373595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen        }
23743c836e7882e88de42e0e600627de433b61e78621Eric Laurent        //TODO: save the extension sampling rate value in meta data =>
23753c836e7882e88de42e0e600627de433b61e78621Eric Laurent        //      mLastTrack->meta->setInt32(kKeyExtSampleRate, extSampleRate);
2376ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2377ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2378ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (numChannels == 0) {
2379ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_UNSUPPORTED;
2380ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2381ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2382ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevSampleRate;
2383ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
2384ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2385ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevSampleRate != sampleRate) {
23863856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("mpeg4 audio sample rate different from previous setting. "
2387ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevSampleRate, sampleRate);
2388ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2389ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2390ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
2391ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2392ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevChannelCount;
2393ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
2394ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2395ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevChannelCount != numChannels) {
23963856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("mpeg4 audio channel count different from previous setting. "
2397ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevChannelCount, numChannels);
2398ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2399ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2400ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
2401ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2402ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    return OK;
2403ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber}
2404ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
240520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
240620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
240720111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::MPEG4Source(
240820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        const sp<MetaData> &format,
2409693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &dataSource,
241048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        int32_t timeScale,
241105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const sp<SampleTable> &sampleTable,
241205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        Vector<SidxEntry> &sidx,
241305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t firstMoofOffset)
241420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mFormat(format),
241520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDataSource(dataSource),
241648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber      mTimescale(timeScale),
241720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSampleTable(sampleTable),
241820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCurrentSampleIndex(0),
241905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentFragmentIndex(0),
242005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mSegments(sidx),
242105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mFirstMoofOffset(firstMoofOffset),
242205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentMoofOffset(firstMoofOffset),
242305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentTime(0),
2424ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoAllocSize(0),
2425ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoSizes(NULL),
2426ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoOffsetsAllocSize(0),
2427ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoOffsets(NULL),
242820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mIsAVC(false),
24296064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber      mNALLengthSize(0),
243020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mStarted(false),
243120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mGroup(NULL),
243220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mBuffer(NULL),
2433dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber      mWantsNALFragments(false),
24340024245e134467d120b40099da16c467dc365e76Andreas Huber      mSrcBuffer(NULL) {
2435ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2436ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mFormat->findInt32(kKeyCryptoMode, &mCryptoMode);
243748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    mDefaultIVSize = 0;
2438ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mFormat->findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize);
2439ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t keytype;
2440ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    const void *key;
2441ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    size_t keysize;
2442ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mFormat->findData(kKeyCryptoKey, &keytype, &key, &keysize)) {
2443ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        CHECK(keysize <= 16);
2444ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memset(mCryptoKey, 0, 16);
2445ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memcpy(mCryptoKey, key, keysize);
2446ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2447ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
244820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
244920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mFormat->findCString(kKeyMIMEType, &mime);
2450dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(success);
245120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
245218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber    mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
24536064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
24546064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    if (mIsAVC) {
24556064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        uint32_t type;
24566064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const void *data;
24576064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t size;
24586064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(format->findData(kKeyAVCC, &type, &data, &size));
24596064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
24606064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const uint8_t *ptr = (const uint8_t *)data;
24616064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
24626064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(size >= 7);
2463ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
24646064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
24656064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        // The number of bytes used to encode the length of a NAL unit.
24666064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        mNALLengthSize = 1 + (ptr[4] & 3);
24676064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
246805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
246905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    CHECK(format->findInt32(kKeyTrackID, &mTrackId));
247005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
247105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mFirstMoofOffset != 0) {
247205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t offset = mFirstMoofOffset;
247305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        parseChunk(&offset);
247405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
247520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
247620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
247720111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::~MPEG4Source() {
247820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mStarted) {
247920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        stop();
248020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
2481ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    free(mCurrentSampleInfoSizes);
2482ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    free(mCurrentSampleInfoOffsets);
248320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
248420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
248520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::start(MetaData *params) {
24867b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
24877b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
2488dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(!mStarted);
248920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
249020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t val;
2491dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (params && params->findInt32(kKeyWantsNALFragments, &val)
249220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        && val != 0) {
2493dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = true;
249420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    } else {
2495dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = false;
249620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
249720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
249820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = new MediaBufferGroup;
249920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2500738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    int32_t max_size;
2501738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
250220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2503738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    mGroup->add_buffer(new MediaBuffer(max_size));
25040024245e134467d120b40099da16c467dc365e76Andreas Huber
25050024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = new uint8_t[max_size];
250620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
250720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = true;
250820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
250920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
251020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
251120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
251220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::stop() {
25137b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
25147b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
2515dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
251620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
251720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mBuffer != NULL) {
251820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->release();
251920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
252020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
252120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
25220024245e134467d120b40099da16c467dc365e76Andreas Huber    delete[] mSrcBuffer;
25230024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = NULL;
25240024245e134467d120b40099da16c467dc365e76Andreas Huber
252520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    delete mGroup;
252620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = NULL;
252720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
252820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = false;
252920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mCurrentSampleIndex = 0;
253020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
253120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
253220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
253320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
253405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseChunk(off64_t *offset) {
253505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t hdr[2];
253605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
253705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_IO;
253805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
253905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t chunk_size = ntohl(hdr[0]);
254005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t chunk_type = ntohl(hdr[1]);
254105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t data_offset = *offset + 8;
254205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
254305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (chunk_size == 1) {
254405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
254505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_IO;
254605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
254705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        chunk_size = ntoh64(chunk_size);
254805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        data_offset += 8;
254905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
255005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (chunk_size < 16) {
255105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            // The smallest valid chunk is 16 bytes long in this case.
255205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
255305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
255405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (chunk_size < 8) {
255505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // The smallest valid chunk is 8 bytes long.
255605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
255705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
255805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
255905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    char chunk[5];
256005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    MakeFourCCString(chunk_type, chunk);
256105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Source chunk %s @ %llx", chunk, *offset);
256205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
256305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t chunk_data_size = *offset + chunk_size - data_offset;
256405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
256505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    switch(chunk_type) {
256605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
256705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'r', 'a', 'f'):
256805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('m', 'o', 'o', 'f'): {
256905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t stop_offset = *offset + chunk_size;
257005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset = data_offset;
257105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            while (*offset < stop_offset) {
257205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err = parseChunk(offset);
257305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (err != OK) {
257405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return err;
257505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
257605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
257705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
2578ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // *offset points to the mdat box following this moof
257905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                parseChunk(offset); // doesn't actually parse it, just updates offset
258005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mNextMoofOffset = *offset;
258105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
258205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
258305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
258405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
258505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'f', 'h', 'd'): {
258605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err;
258705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if ((err = parseTrackFragmentHeader(data_offset, chunk_data_size)) != OK) {
258805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return err;
258905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
259005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                *offset += chunk_size;
259105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                break;
259205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
259305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
259405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'r', 'u', 'n'): {
259505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err;
259605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (mLastParsedTrackId == mTrackId) {
259705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    if ((err = parseTrackFragmentRun(data_offset, chunk_data_size)) != OK) {
259805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        return err;
259905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    }
260005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
260105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
260205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                *offset += chunk_size;
260305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                break;
260405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
260505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2606ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'a', 'i', 'z'): {
2607ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            status_t err;
2608ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((err = parseSampleAuxiliaryInformationSizes(data_offset, chunk_data_size)) != OK) {
2609ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return err;
2610ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
2611ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
2612ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
2613ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2614ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'a', 'i', 'o'): {
2615ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            status_t err;
2616ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((err = parseSampleAuxiliaryInformationOffsets(data_offset, chunk_data_size)) != OK) {
2617ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return err;
2618ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
2619ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
2620ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
2621ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2622ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2623ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('m', 'd', 'a', 't'): {
2624ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // parse DRM info if present
2625ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("MPEG4Source::parseChunk mdat");
2626ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // if saiz/saoi was previously observed, do something with the sampleinfos
2627ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
2628ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
2629ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2630ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
263105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        default: {
263205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset += chunk_size;
263305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
263405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
263505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
263605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
263705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
263805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2639ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissenstatus_t MPEG4Source::parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size) {
2640ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("parseSampleAuxiliaryInformationSizes");
2641ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // 14496-12 8.7.12
2642ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t version;
2643ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(
2644ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset, &version, sizeof(version))
2645ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            < (ssize_t)sizeof(version)) {
2646ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
2647ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2648ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2649ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (version != 0) {
2650ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_UNSUPPORTED;
2651ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2652ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
2653ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2654ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t flags;
2655ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt24(offset, &flags)) {
2656ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
2657ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2658ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 3;
2659ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2660ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (flags & 1) {
2661ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        uint32_t tmp;
2662ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
2663ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_MALFORMED;
2664ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2665ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentAuxInfoType = tmp;
2666ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        offset += 4;
2667ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
2668ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_MALFORMED;
2669ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2670ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentAuxInfoTypeParameter = tmp;
2671ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        offset += 4;
2672ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2673ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2674ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t defsize;
2675ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(offset, &defsize, 1) != 1) {
2676ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_MALFORMED;
2677ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2678ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mCurrentDefaultSampleInfoSize = defsize;
2679ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
2680ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2681ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t smplcnt;
2682ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &smplcnt)) {
2683ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_MALFORMED;
2684ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
268548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    mCurrentSampleInfoCount = smplcnt;
2686ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 4;
2687ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
268848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (mCurrentDefaultSampleInfoSize != 0) {
268948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        ALOGV("@@@@ using default sample info size of %d", mCurrentDefaultSampleInfoSize);
269048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return OK;
269148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
2692ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (smplcnt > mCurrentSampleInfoAllocSize) {
2693ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoSizes = (uint8_t*) realloc(mCurrentSampleInfoSizes, smplcnt);
2694ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoAllocSize = smplcnt;
2695ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2696ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2697ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mDataSource->readAt(offset, mCurrentSampleInfoSizes, smplcnt);
2698ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    return OK;
2699ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen}
2700ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2701ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissenstatus_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size) {
2702ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("parseSampleAuxiliaryInformationOffsets");
2703ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // 14496-12 8.7.13
2704ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t version;
2705ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(offset, &version, sizeof(version)) != 1) {
2706ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
2707ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2708ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
2709ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2710ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t flags;
2711ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt24(offset, &flags)) {
2712ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
2713ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2714ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 3;
2715ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2716ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t entrycount;
2717ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &entrycount)) {
2718ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
2719ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2720ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 4;
2721937c6bedd4b6e5c6cb29a238eb459047dedd3486Wei Jia    if (entrycount == 0) {
2722937c6bedd4b6e5c6cb29a238eb459047dedd3486Wei Jia        return OK;
2723937c6bedd4b6e5c6cb29a238eb459047dedd3486Wei Jia    }
2724937c6bedd4b6e5c6cb29a238eb459047dedd3486Wei Jia    if (entrycount > UINT32_MAX / 8) {
2725937c6bedd4b6e5c6cb29a238eb459047dedd3486Wei Jia        return ERROR_MALFORMED;
2726937c6bedd4b6e5c6cb29a238eb459047dedd3486Wei Jia    }
2727ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2728ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (entrycount > mCurrentSampleInfoOffsetsAllocSize) {
2729937c6bedd4b6e5c6cb29a238eb459047dedd3486Wei Jia        uint64_t *newPtr = (uint64_t *)realloc(mCurrentSampleInfoOffsets, entrycount * 8);
2730937c6bedd4b6e5c6cb29a238eb459047dedd3486Wei Jia        if (newPtr == NULL) {
2731937c6bedd4b6e5c6cb29a238eb459047dedd3486Wei Jia            return NO_MEMORY;
2732937c6bedd4b6e5c6cb29a238eb459047dedd3486Wei Jia        }
2733937c6bedd4b6e5c6cb29a238eb459047dedd3486Wei Jia        mCurrentSampleInfoOffsets = newPtr;
2734ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoOffsetsAllocSize = entrycount;
2735ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2736ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mCurrentSampleInfoOffsetCount = entrycount;
2737ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2738937c6bedd4b6e5c6cb29a238eb459047dedd3486Wei Jia    if (mCurrentSampleInfoOffsets == NULL) {
2739937c6bedd4b6e5c6cb29a238eb459047dedd3486Wei Jia        return OK;
2740937c6bedd4b6e5c6cb29a238eb459047dedd3486Wei Jia    }
2741937c6bedd4b6e5c6cb29a238eb459047dedd3486Wei Jia
2742ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < entrycount; i++) {
2743ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (version == 0) {
2744ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t tmp;
2745ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (!mDataSource->getUInt32(offset, &tmp)) {
2746ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
2747ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
2748ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mCurrentSampleInfoOffsets[i] = tmp;
2749ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset += 4;
2750ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        } else {
2751ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint64_t tmp;
2752ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (!mDataSource->getUInt64(offset, &tmp)) {
2753ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
2754ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
2755ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mCurrentSampleInfoOffsets[i] = tmp;
2756ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset += 8;
2757ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2758ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2759ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2760ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // parse clear/encrypted data
2761ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2762ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    off64_t drmoffset = mCurrentSampleInfoOffsets[0]; // from moof
2763ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2764ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    drmoffset += mCurrentMoofOffset;
2765ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int ivlength;
2766ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    CHECK(mFormat->findInt32(kKeyCryptoDefaultIVSize, &ivlength));
276748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
2768073e4f6748f5d7deb095c42fad9271cb99e22d07Marco Nelissen    // only 0, 8 and 16 byte initialization vectors are supported
2769073e4f6748f5d7deb095c42fad9271cb99e22d07Marco Nelissen    if (ivlength != 0 && ivlength != 8 && ivlength != 16) {
2770073e4f6748f5d7deb095c42fad9271cb99e22d07Marco Nelissen        ALOGW("unsupported IV length: %d", ivlength);
2771073e4f6748f5d7deb095c42fad9271cb99e22d07Marco Nelissen        return ERROR_MALFORMED;
2772073e4f6748f5d7deb095c42fad9271cb99e22d07Marco Nelissen    }
277348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    // read CencSampleAuxiliaryDataFormats
2774ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mCurrentSampleInfoCount; i++) {
2775073e4f6748f5d7deb095c42fad9271cb99e22d07Marco Nelissen        if (i >= mCurrentSamples.size()) {
2776073e4f6748f5d7deb095c42fad9271cb99e22d07Marco Nelissen            ALOGW("too few samples");
2777073e4f6748f5d7deb095c42fad9271cb99e22d07Marco Nelissen            break;
2778073e4f6748f5d7deb095c42fad9271cb99e22d07Marco Nelissen        }
2779ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Sample *smpl = &mCurrentSamples.editItemAt(i);
2780ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2781ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memset(smpl->iv, 0, 16);
2782ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (mDataSource->readAt(drmoffset, smpl->iv, ivlength) != ivlength) {
2783ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_IO;
2784ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2785ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2786ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        drmoffset += ivlength;
2787ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
278848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        int32_t smplinfosize = mCurrentDefaultSampleInfoSize;
278948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        if (smplinfosize == 0) {
279048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smplinfosize = mCurrentSampleInfoSizes[i];
2791ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
279248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        if (smplinfosize > ivlength) {
279348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint16_t numsubsamples;
279448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (!mDataSource->getUInt16(drmoffset, &numsubsamples)) {
2795ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
2796ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
2797ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            drmoffset += 2;
279848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            for (size_t j = 0; j < numsubsamples; j++) {
279948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                uint16_t numclear;
280048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                uint32_t numencrypted;
280148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                if (!mDataSource->getUInt16(drmoffset, &numclear)) {
280248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                    return ERROR_IO;
280348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                }
280448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                drmoffset += 2;
280548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                if (!mDataSource->getUInt32(drmoffset, &numencrypted)) {
280648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                    return ERROR_IO;
280748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                }
280848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                drmoffset += 4;
280948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->clearsizes.add(numclear);
281048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->encryptedsizes.add(numencrypted);
2811ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
281248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        } else {
281348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smpl->clearsizes.add(0);
281448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smpl->encryptedsizes.add(smpl->size);
2815ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2816ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2817ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2818ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2819ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    return OK;
2820ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen}
2821ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
282205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentHeader(off64_t offset, off64_t size) {
282305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
282405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 8) {
282505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
282605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
282705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
282805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
2829ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags
283005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
283105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
283205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
283305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & 0xff000000) {
283405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
283505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
283605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
283705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, (uint32_t*)&mLastParsedTrackId)) {
283805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
283905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
284005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
284105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mLastParsedTrackId != mTrackId) {
284205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // this is not the right track, skip it
284305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
284405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
284505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
284605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mFlags = flags;
284705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mTrackID = mLastParsedTrackId;
284805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 8;
284905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 8;
285005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
285105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("fragment header: %08x %08x", flags, mTrackFragmentHeaderInfo.mTrackID);
285205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
285305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent) {
285405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 8) {
285505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
285605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
285705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
285805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset, &mTrackFragmentHeaderInfo.mBaseDataOffset)) {
285905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
286005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
286105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 8;
286205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 8;
286305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
286405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
286505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent) {
286605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
286705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
286805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
286905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
287005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mSampleDescriptionIndex)) {
287105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
287205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
287305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
287405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
287505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
287605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
287705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
287805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
287905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
288005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
288105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
288205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleDuration)) {
288305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
288405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
288505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
288605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
288705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
288805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
288905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
289005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
289105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
289205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
289305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
289405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleSize)) {
289505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
289605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
289705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
289805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
289905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
290005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
290105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
290205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
290305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
290405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
290505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
290605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleFlags)) {
290705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
290805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
290905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
291005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
291105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
291205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
291305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!(flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent)) {
291405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mTrackFragmentHeaderInfo.mBaseDataOffset = mCurrentMoofOffset;
291505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
291605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
291705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mDataOffset = 0;
291805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
291905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
292005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
292105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentRun(off64_t offset, off64_t size) {
292205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
292305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Extractor::parseTrackFragmentRun");
292405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 8) {
292505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
292605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
292705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
292805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    enum {
292905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kDataOffsetPresent                  = 0x01,
293005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kFirstSampleFlagsPresent            = 0x04,
293105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleDurationPresent              = 0x100,
293205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleSizePresent                  = 0x200,
293305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleFlagsPresent                 = 0x400,
293405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleCompositionTimeOffsetPresent = 0x800,
293505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
293605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
293705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
293805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) {
293905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
294005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
294105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("fragment run flags: %08x", flags);
294205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
294305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & 0xff000000) {
294405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
294505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
294605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
294705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if ((flags & kFirstSampleFlagsPresent) && (flags & kSampleFlagsPresent)) {
294805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // These two shall not be used together.
294905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
295005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
295105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
295205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t sampleCount;
295305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, &sampleCount)) {
295405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
295505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
295605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 8;
295705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 8;
295805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
295905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t dataOffset = mTrackFragmentHeaderInfo.mDataOffset;
296005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
296105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t firstSampleFlags = 0;
296205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
296305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kDataOffsetPresent) {
296405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
296505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
296605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
296705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
296805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int32_t dataOffsetDelta;
296905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, (uint32_t*)&dataOffsetDelta)) {
297005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
297105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
297205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
297305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        dataOffset = mTrackFragmentHeaderInfo.mBaseDataOffset + dataOffsetDelta;
297405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
297505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
297605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
297705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
297805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
297905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kFirstSampleFlagsPresent) {
298005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
298105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
298205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
298305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
298405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &firstSampleFlags)) {
298505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
298605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
298705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
298805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
298905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
299005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
299105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t sampleDuration = 0, sampleSize = 0, sampleFlags = 0,
299205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen             sampleCtsOffset = 0;
299305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
299405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size_t bytesPerSample = 0;
299505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleDurationPresent) {
299605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
299705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
299805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
299905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration;
300005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
300105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration;
300205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
300305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
300405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleSizePresent) {
300505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
300605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
300705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
300805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
300905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
301005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
301105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
301205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
301305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleFlagsPresent) {
301405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
301505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
301605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
301705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
301805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
301905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
302005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
302105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
302205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleCompositionTimeOffsetPresent) {
302305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
302405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
302505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleCtsOffset = 0;
302605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
302705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
302805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < sampleCount * bytesPerSample) {
302905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
303005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
303105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
303205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Sample tmp;
303305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    for (uint32_t i = 0; i < sampleCount; ++i) {
303405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleDurationPresent) {
303505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleDuration)) {
303605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
303705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
303805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
303905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
304005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
304105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleSizePresent) {
304205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleSize)) {
304305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
304405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
304505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
304605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
304705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
304805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleFlagsPresent) {
304905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleFlags)) {
305005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
305105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
305205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
305305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
305405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
305505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleCompositionTimeOffsetPresent) {
305605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleCtsOffset)) {
305705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
305805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
305905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
306005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
306105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3062ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        ALOGV("adding sample %d at offset 0x%08llx, size %u, duration %u, "
3063ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen              " flags 0x%08x", i + 1,
306405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dataOffset, sampleSize, sampleDuration,
306505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                (flags & kFirstSampleFlagsPresent) && i == 0
306605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ? firstSampleFlags : sampleFlags);
306705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.offset = dataOffset;
306805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.size = sampleSize;
306905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.duration = sampleDuration;
307005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentSamples.add(tmp);
307105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
307205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        dataOffset += sampleSize;
307305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
307405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
307505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mDataOffset = dataOffset;
307605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
307705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
307805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
307905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
308020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> MPEG4Source::getFormat() {
30817b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
30827b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
308320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return mFormat;
308420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
308520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30866064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const {
30876064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    switch (mNALLengthSize) {
30886064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 1:
30896064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return *data;
30906064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 2:
30916064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U16_AT(data);
30926064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 3:
30936064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return ((size_t)data[0] << 16) | U16_AT(&data[1]);
30946064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 4:
30956064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U32_AT(data);
30966064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
30976064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
30986064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // This cannot happen, mNALLengthSize springs to life by adding 1 to
30996064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // a 2-bit integer.
31006064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    CHECK(!"Should not be here.");
31016064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
31026064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    return 0;
31036064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber}
31046064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
310520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::read(
310620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
31077b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
31087b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
3109dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
311020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
311105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mFirstMoofOffset > 0) {
311205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return fragmentedRead(out, options);
311305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
311405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
311520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *out = NULL;
311620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3117abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    int64_t targetSampleTimeUs = -1;
3118abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
311920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t seekTimeUs;
3120abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
3121abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
3122abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t findFlags = 0;
3123abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        switch (mode) {
3124abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_PREVIOUS_SYNC:
3125abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagBefore;
3126abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3127abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_NEXT_SYNC:
3128abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagAfter;
3129abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3130abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST_SYNC:
3131abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST:
3132abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagClosest;
3133abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3134abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            default:
3135abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                CHECK(!"Should not be here.");
3136abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3137abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3138abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
313920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        uint32_t sampleIndex;
3140abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        status_t err = mSampleTable->findSampleAtTime(
314120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                seekTimeUs * mTimescale / 1000000,
3142abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                &sampleIndex, findFlags);
3143abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3144abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
3145abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // We found the closest sample already, now we want the sync
3146abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // sample preceding it (or the sample itself of course), even
3147abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // if the subsequent sync sample is closer.
3148abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            findFlags = SampleTable::kFlagBefore;
3149abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3150abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3151abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleIndex;
3152abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (err == OK) {
3153abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            err = mSampleTable->findSyncSampleNear(
3154abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    sampleIndex, &syncSampleIndex, findFlags);
3155abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
315620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3157788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        uint32_t sampleTime;
3158788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        if (err == OK) {
3159788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber            err = mSampleTable->getMetaDataForSample(
3160788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber                    sampleIndex, NULL, NULL, &sampleTime);
3161788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        }
3162788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber
316320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (err != OK) {
31645295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            if (err == ERROR_OUT_OF_RANGE) {
31655295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // An attempt to seek past the end of the stream would
31665295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // normally cause this ERROR_OUT_OF_RANGE error. Propagating
31675295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // this all the way to the MediaPlayer would cause abnormal
31685295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // termination. Legacy behaviour appears to be to behave as if
31695295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // we had seeked to the end of stream, ending normally.
31705295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                err = ERROR_END_OF_STREAM;
31715295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            }
317205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("end of stream");
317320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return err;
317420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
317520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3176abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
3177abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
3178abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3179abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3180abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#if 0
3181abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleTime;
3182abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
3183abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    syncSampleIndex, NULL, NULL, &syncSampleTime));
3184abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3185df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("seek to time %lld us => sample at time %lld us, "
3186abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             "sync sample at time %lld us",
3187abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             seekTimeUs,
3188abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             sampleTime * 1000000ll / mTimescale,
3189abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             syncSampleTime * 1000000ll / mTimescale);
3190abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#endif
3191abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3192abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        mCurrentSampleIndex = syncSampleIndex;
319320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mBuffer != NULL) {
319420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
319520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
319620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
319720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
319820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // fall through
319920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
320020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3201c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset;
32020024245e134467d120b40099da16c467dc365e76Andreas Huber    size_t size;
32034678a6dc5f09008481524949a9667af5a6190374Andreas Huber    uint32_t cts;
32048bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    bool isSyncSample;
3205dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool newBuffer = false;
3206dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (mBuffer == NULL) {
3207dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        newBuffer = true;
320820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3209c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        status_t err =
3210c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber            mSampleTable->getMetaDataForSample(
32114678a6dc5f09008481524949a9667af5a6190374Andreas Huber                    mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample);
321220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3213dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
3214dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
3215dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3216dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3217dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        err = mGroup->acquire_buffer(&mBuffer);
3218c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
3219dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
3220ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            CHECK(mBuffer == NULL);
3221dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
3222dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3223f11e95b21007f24e5ab77298370855f9f085b2d7Marco Nelissen        if (size > mBuffer->size()) {
3224f11e95b21007f24e5ab77298370855f9f085b2d7Marco Nelissen            ALOGE("buffer too small: %zu > %zu", size, mBuffer->size());
3225f11e95b21007f24e5ab77298370855f9f085b2d7Marco Nelissen            return ERROR_BUFFER_TOO_SMALL;
3226f11e95b21007f24e5ab77298370855f9f085b2d7Marco Nelissen        }
32270024245e134467d120b40099da16c467dc365e76Andreas Huber    }
322820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3229dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (!mIsAVC || mWantsNALFragments) {
3230dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (newBuffer) {
3231dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ssize_t num_bytes_read =
323234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
3233dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3234dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            if (num_bytes_read < (ssize_t)size) {
3235dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer->release();
3236dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer = NULL;
3237dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3238dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                return ERROR_IO;
3239dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            }
3240dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
32417b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber            CHECK(mBuffer != NULL);
3242dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->set_range(0, size);
3243dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->meta_data()->clear();
324448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mBuffer->meta_data()->setInt64(
32454678a6dc5f09008481524949a9667af5a6190374Andreas Huber                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
3246abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3247abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            if (targetSampleTimeUs >= 0) {
3248abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                mBuffer->meta_data()->setInt64(
3249abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                        kKeyTargetTime, targetSampleTimeUs);
3250abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            }
3251abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
32528bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            if (isSyncSample) {
32538bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
32548bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            }
32558bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
3256dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ++mCurrentSampleIndex;
3257dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3258dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3259dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (!mIsAVC) {
3260dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            *out = mBuffer;
3261dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
3262dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3263dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return OK;
3264dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3265dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3266dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Each NAL unit is split up into its constituent fragments and
3267dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // each one of them returned in its own buffer.
3268dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
32696064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(mBuffer->range_length() >= mNALLengthSize);
3270dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3271dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        const uint8_t *src =
3272dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
3273dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
32746064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t nal_size = parseNALSize(src);
3275e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
327629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("incomplete NAL unit.");
3277e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3278e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer->release();
3279e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer = NULL;
3280e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3281e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            return ERROR_MALFORMED;
3282e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        }
3283dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3284dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        MediaBuffer *clone = mBuffer->clone();
32857b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(clone != NULL);
32866064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
3287dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
32887b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(mBuffer != NULL);
3289dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mBuffer->set_range(
32906064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_offset() + mNALLengthSize + nal_size,
32916064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_length() - mNALLengthSize - nal_size);
3292dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3293dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (mBuffer->range_length() == 0) {
3294dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->release();
3295dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
3296dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3297dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3298dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        *out = clone;
3299dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3300dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        return OK;
3301dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    } else {
3302dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Whole NAL units are returned but each fragment is prefixed by
3303dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // the start code (0x00 00 00 01).
3304dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        ssize_t num_bytes_read = 0;
3305dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        int32_t drm = 0;
3306dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
3307dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (usesDRM) {
3308dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            num_bytes_read =
3309dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
3310dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
3311dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
3312dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
331320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
331420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (num_bytes_read < (ssize_t)size) {
331520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
331620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
331720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3318dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return ERROR_IO;
331920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
332020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3321dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (usesDRM) {
3322dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK(mBuffer != NULL);
3323dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            mBuffer->set_range(0, size);
33246064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
3325dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
3326dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            uint8_t *dstData = (uint8_t *)mBuffer->data();
3327dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size_t srcOffset = 0;
3328dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size_t dstOffset = 0;
3329e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3330dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            while (srcOffset < size) {
333167a30ebfe785f7cd5ecfb0d2fb487e54536a3d48Lajos Molnar                bool isMalFormed = !isInRange(0u, size, srcOffset, mNALLengthSize);
333234fe252c89e33572d01fea981b58d7b115e76164James Dong                size_t nalLength = 0;
333334fe252c89e33572d01fea981b58d7b115e76164James Dong                if (!isMalFormed) {
333434fe252c89e33572d01fea981b58d7b115e76164James Dong                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
333534fe252c89e33572d01fea981b58d7b115e76164James Dong                    srcOffset += mNALLengthSize;
333667a30ebfe785f7cd5ecfb0d2fb487e54536a3d48Lajos Molnar                    isMalFormed = !isInRange(0u, size, srcOffset, nalLength);
333734fe252c89e33572d01fea981b58d7b115e76164James Dong                }
3338e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
333934fe252c89e33572d01fea981b58d7b115e76164James Dong                if (isMalFormed) {
334029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                    ALOGE("Video is malformed");
3341dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    mBuffer->release();
3342dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    mBuffer = NULL;
3343dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return ERROR_MALFORMED;
3344dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
3345dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
3346dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                if (nalLength == 0) {
3347dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    continue;
3348dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
3349dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3350dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                CHECK(dstOffset + 4 <= mBuffer->size());
3351dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3352dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3353dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3354dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3355dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 1;
3356dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
3357dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                srcOffset += nalLength;
3358dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstOffset += nalLength;
3359dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
3360dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK_EQ(srcOffset, size);
3361dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK(mBuffer != NULL);
3362dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            mBuffer->set_range(0, dstOffset);
3363dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3364dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
336520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->meta_data()->clear();
336648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        mBuffer->meta_data()->setInt64(
33674678a6dc5f09008481524949a9667af5a6190374Andreas Huber                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
3368abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3369abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (targetSampleTimeUs >= 0) {
3370abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            mBuffer->meta_data()->setInt64(
3371abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    kKeyTargetTime, targetSampleTimeUs);
3372abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3373abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
33748bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        if (isSyncSample) {
33758bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
33768bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        }
33778bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
337820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        ++mCurrentSampleIndex;
337920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
338020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        *out = mBuffer;
338120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
338220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
338320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
338420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
338520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
338620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
338705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::fragmentedRead(
338805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MediaBuffer **out, const ReadOptions *options) {
338905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
339005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Source::fragmentedRead");
339105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
339205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    CHECK(mStarted);
339305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
339405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    *out = NULL;
339505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
339605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t targetSampleTimeUs = -1;
339705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
339805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t seekTimeUs;
339905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ReadOptions::SeekMode mode;
340005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
340105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
340205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int numSidxEntries = mSegments.size();
340305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (numSidxEntries != 0) {
340405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            int64_t totalTime = 0;
340505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t totalOffset = mFirstMoofOffset;
340605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            for (int i = 0; i < numSidxEntries; i++) {
340705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                const SidxEntry *se = &mSegments[i];
340805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (totalTime + se->mDurationUs > seekTimeUs) {
340905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    // The requested time is somewhere in this segment
341005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    if ((mode == ReadOptions::SEEK_NEXT_SYNC) ||
341105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        (mode == ReadOptions::SEEK_CLOSEST_SYNC &&
341205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        (seekTimeUs - totalTime) > (totalTime + se->mDurationUs - seekTimeUs))) {
341305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        // requested next sync, or closest sync and it was closer to the end of
341405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        // this segment
341505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        totalTime += se->mDurationUs;
341605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        totalOffset += se->mSize;
341705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    }
341805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    break;
341905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
342005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                totalTime += se->mDurationUs;
342105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                totalOffset += se->mSize;
342205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
342305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentMoofOffset = totalOffset;
342405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentSamples.clear();
342505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentSampleIndex = 0;
342605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        parseChunk(&totalOffset);
342705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentTime = totalTime * mTimescale / 1000000ll;
342805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
342905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
343005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer != NULL) {
343105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
343205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
343305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
343405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
343505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // fall through
343605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
343705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
343805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t offset = 0;
343905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size_t size;
344005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t cts = 0;
344105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    bool isSyncSample = false;
344205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    bool newBuffer = false;
344305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mBuffer == NULL) {
344405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        newBuffer = true;
344505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
344605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mCurrentSampleIndex >= mCurrentSamples.size()) {
344705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            // move to next fragment
344805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            Sample lastSample = mCurrentSamples[mCurrentSamples.size() - 1];
344905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t nextMoof = mNextMoofOffset; // lastSample.offset + lastSample.size;
345005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentMoofOffset = nextMoof;
345105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentSamples.clear();
345205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentSampleIndex = 0;
345305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            parseChunk(&nextMoof);
345405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (mCurrentSampleIndex >= mCurrentSamples.size()) {
345505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return ERROR_END_OF_STREAM;
345605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
345705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
345805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
345905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
346005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset = smpl->offset;
346105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size = smpl->size;
346205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        cts = mCurrentTime;
346305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentTime += smpl->duration;
346405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        isSyncSample = (mCurrentSampleIndex == 0); // XXX
346505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
346605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        status_t err = mGroup->acquire_buffer(&mBuffer);
346705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
346805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (err != OK) {
346905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer == NULL);
347005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("acquire_buffer returned %d", err);
347105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return err;
347205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
3473f11e95b21007f24e5ab77298370855f9f085b2d7Marco Nelissen        if (size > mBuffer->size()) {
3474f11e95b21007f24e5ab77298370855f9f085b2d7Marco Nelissen            ALOGE("buffer too small: %zu > %zu", size, mBuffer->size());
3475f11e95b21007f24e5ab77298370855f9f085b2d7Marco Nelissen            return ERROR_BUFFER_TOO_SMALL;
3476f11e95b21007f24e5ab77298370855f9f085b2d7Marco Nelissen        }
347705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
347805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
347948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
348048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    const sp<MetaData> bufmeta = mBuffer->meta_data();
348148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    bufmeta->clear();
348248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (smpl->encryptedsizes.size()) {
348348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // store clear/encrypted lengths in metadata
348448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyPlainSizes, 0,
348548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->clearsizes.array(), smpl->clearsizes.size() * 4);
348648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyEncryptedSizes, 0,
348748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
348848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
348948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
349048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setInt32(kKeyCryptoMode, mCryptoMode);
349148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16);
349248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
349348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
349405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mIsAVC || mWantsNALFragments) {
349505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (newBuffer) {
3496f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            if (!isInRange((size_t)0u, mBuffer->size(), size)) {
3497f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                mBuffer->release();
3498f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                mBuffer = NULL;
3499f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih
3500f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                ALOGE("fragmentedRead ERROR_MALFORMED size %zu", size);
3501f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                return ERROR_MALFORMED;
3502f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            }
3503f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih
350405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ssize_t num_bytes_read =
350505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
350605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
350705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (num_bytes_read < (ssize_t)size) {
350805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->release();
350905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer = NULL;
351005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3511f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                ALOGE("i/o error");
351205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_IO;
351305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
351405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
351505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
351605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, size);
351705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt64(
351805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
351905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
352005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (targetSampleTimeUs >= 0) {
352105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->meta_data()->setInt64(
352205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        kKeyTargetTime, targetSampleTimeUs);
352305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
352405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
352505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (isSyncSample) {
352605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
352705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
352805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
352905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ++mCurrentSampleIndex;
353005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
353105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
353205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mIsAVC) {
353305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *out = mBuffer;
353405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
353505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
353605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return OK;
353705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
353805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
353905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // Each NAL unit is split up into its constituent fragments and
354005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // each one of them returned in its own buffer.
354105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
354205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(mBuffer->range_length() >= mNALLengthSize);
354305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
354405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const uint8_t *src =
354505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
354605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
354705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size_t nal_size = parseNALSize(src);
354805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
354905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGE("incomplete NAL unit.");
355005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
355105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
355205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
355305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
355405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
355505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
355605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
355705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MediaBuffer *clone = mBuffer->clone();
355805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(clone != NULL);
355905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
356005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
356105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(mBuffer != NULL);
356205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer->set_range(
356305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->range_offset() + mNALLengthSize + nal_size,
356405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->range_length() - mNALLengthSize - nal_size);
356505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
356605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer->range_length() == 0) {
356705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
356805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
356905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
357005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
357105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        *out = clone;
357205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
357305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
357405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
357505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV("whole NAL");
357605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // Whole NAL units are returned but each fragment is prefixed by
357705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // the start code (0x00 00 00 01).
357805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ssize_t num_bytes_read = 0;
357905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int32_t drm = 0;
358005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
3581f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih        void *data = NULL;
3582f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih        bool isMalFormed = false;
358305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (usesDRM) {
3584f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            if (mBuffer == NULL || !isInRange((size_t)0u, mBuffer->size(), size)) {
3585f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                isMalFormed = true;
3586f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            } else {
3587f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                data = mBuffer->data();
3588f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            }
358905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else {
3590f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            int32_t max_size;
3591f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            if (mFormat == NULL
3592f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                    || !mFormat->findInt32(kKeyMaxInputSize, &max_size)
3593f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                    || !isInRange((size_t)0u, (size_t)max_size, size)) {
3594f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                isMalFormed = true;
3595f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            } else {
3596f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                data = mSrcBuffer;
3597f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            }
359805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
359905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3600f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih        if (isMalFormed || data == NULL) {
3601f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            ALOGE("isMalFormed size %zu", size);
3602f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            if (mBuffer != NULL) {
3603f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                mBuffer->release();
3604f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                mBuffer = NULL;
3605f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            }
3606f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            return ERROR_MALFORMED;
3607f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih        }
3608f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih        num_bytes_read = mDataSource->readAt(offset, data, size);
3609f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih
361005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (num_bytes_read < (ssize_t)size) {
361105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
361205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
361305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3614f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih            ALOGE("i/o error");
361505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_IO;
361605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
361705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
361805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (usesDRM) {
361905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
362005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, size);
362105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
362205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else {
362305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            uint8_t *dstData = (uint8_t *)mBuffer->data();
362405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            size_t srcOffset = 0;
362505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            size_t dstOffset = 0;
362605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
362705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            while (srcOffset < size) {
3628f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                isMalFormed = !isInRange((size_t)0u, size, srcOffset, mNALLengthSize);
362905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                size_t nalLength = 0;
363005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (!isMalFormed) {
363105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
363205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    srcOffset += mNALLengthSize;
3633f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                    isMalFormed = !isInRange((size_t)0u, size, srcOffset, nalLength)
3634f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                            || !isInRange((size_t)0u, mBuffer->size(), dstOffset, (size_t)4u)
3635f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                            || !isInRange((size_t)0u, mBuffer->size(), dstOffset + 4, nalLength);
363605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
363705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
363805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (isMalFormed) {
3639f810a8298aea13fa177060cdc10c8297eac69c49Robert Shih                    ALOGE("Video is malformed; nalLength %zu", nalLength);
364005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    mBuffer->release();
364105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    mBuffer = NULL;
364205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return ERROR_MALFORMED;
364305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
364405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
364505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (nalLength == 0) {
364605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    continue;
364705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
364805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
364905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                CHECK(dstOffset + 4 <= mBuffer->size());
365005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
365105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
365205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
365305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
365405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 1;
365505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
365605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                srcOffset += nalLength;
365705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstOffset += nalLength;
365805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
365905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK_EQ(srcOffset, size);
366005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
366105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, dstOffset);
366205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
366305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
366405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer->meta_data()->setInt64(
366505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
366605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
366705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (targetSampleTimeUs >= 0) {
366805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt64(
366905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    kKeyTargetTime, targetSampleTimeUs);
367005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
367105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
367205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (isSyncSample) {
367305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
367405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
367505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
367605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ++mCurrentSampleIndex;
367705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
367805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        *out = mBuffer;
367905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer = NULL;
368005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
368105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
368205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
368305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
368405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3685bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas HuberMPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix(
3686bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        const char *mimePrefix) {
3687bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    for (Track *track = mFirstTrack; track != NULL; track = track->next) {
3688bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        const char *mime;
3689bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        if (track->meta != NULL
3690bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                && track->meta->findCString(kKeyMIMEType, &mime)
3691bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) {
3692bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber            return track;
3693bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        }
3694bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    }
3695bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber
3696bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    return NULL;
3697bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber}
3698bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber
36991b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool LegacySniffMPEG4(
3700693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
370120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[8];
370220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
370334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    ssize_t n = source->readAt(4, header, sizeof(header));
370420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (n < (ssize_t)sizeof(header)) {
370520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return false;
370620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
370720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
370820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
3709b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8)
3710b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8)
37110dba73763a04d39faf999dcc5ef12af3c99535a7Andreas Huber        || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
3712ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
3713983b449a27b5fa91eca82ede5204b4341899be62Andreas Huber        || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
371418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
37155a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        *confidence = 0.4;
371620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
371720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return true;
371820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
371920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
372020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return false;
372120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
372220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37231b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool isCompatibleBrand(uint32_t fourcc) {
37241b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    static const uint32_t kCompatibleBrands[] = {
37251b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', 'm'),
37261b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', '2'),
37271b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('a', 'v', 'c', '1'),
37281b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('3', 'g', 'p', '4'),
37291b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '1'),
37301b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '2'),
37314cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong
37324cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        // Won't promise that the following file types can be played.
37334cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        // Just give these file types a chance.
37344cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        FOURCC('q', 't', ' ', ' '),  // Apple's QuickTime
37354cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        FOURCC('M', 'S', 'N', 'V'),  // Sony's PSP
373658fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber
373758fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber        FOURCC('3', 'g', '2', 'a'),  // 3GPP2
373858fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber        FOURCC('3', 'g', '2', 'b'),
37391b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    };
37401b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
37411b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    for (size_t i = 0;
37421b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]);
37431b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         ++i) {
37441b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        if (kCompatibleBrands[i] == fourcc) {
37451b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            return true;
37461b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
37471b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
37481b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
37491b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
37501b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
37511b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
37521b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// Attempt to actually parse the 'ftyp' atom and determine if a suitable
37531b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// compatible brand is present.
3754a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// Also try to identify where this file's metadata ends
3755a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// (end of the 'moov' atom) and report it to the caller as part of
3756a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// the metadata.
37571b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool BetterSniffMPEG4(
3758a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
3759a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        sp<AMessage> *meta) {
3760a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    // We scan up to 128 bytes to identify this file as an MP4.
3761a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    static const off64_t kMaxScanOffset = 128ll;
37621b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
3763a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    off64_t offset = 0ll;
3764a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    bool foundGoodFileType = false;
3765a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    off64_t moovAtomEndOffset = -1ll;
3766a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    bool done = false;
37671b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
3768a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    while (!done && offset < kMaxScanOffset) {
3769a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint32_t hdr[2];
3770a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        if (source->readAt(offset, hdr, 8) < 8) {
3771a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            return false;
3772a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        }
3773a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3774a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint64_t chunkSize = ntohl(hdr[0]);
3775a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint32_t chunkType = ntohl(hdr[1]);
3776a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        off64_t chunkDataOffset = offset + 8;
3777a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3778a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        if (chunkSize == 1) {
3779a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            if (source->readAt(offset + 8, &chunkSize, 8) < 8) {
37801b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                return false;
37811b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
37821b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
3783a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            chunkSize = ntoh64(chunkSize);
3784a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            chunkDataOffset += 8;
3785a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3786a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            if (chunkSize < 16) {
3787a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                // The smallest valid chunk is 16 bytes long in this case.
3788a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                return false;
3789a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            }
3790a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        } else if (chunkSize < 8) {
3791a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            // The smallest valid chunk is 8 bytes long.
3792a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            return false;
3793a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        }
3794a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3795a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        off64_t chunkDataSize = offset + chunkSize - chunkDataOffset;
3796a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
379705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        char chunkstring[5];
379805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MakeFourCCString(chunkType, chunkstring);
379905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV("saw chunk type %s, size %lld @ %lld", chunkstring, chunkSize, offset);
3800a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        switch (chunkType) {
3801a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            case FOURCC('f', 't', 'y', 'p'):
3802a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            {
3803a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                if (chunkDataSize < 8) {
3804a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    return false;
3805a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
3806a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3807a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4;
3808a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
3809a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (i == 1) {
3810a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        // Skip this index, it refers to the minorVersion,
3811a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        // not a brand.
3812a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        continue;
3813a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
3814a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3815a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    uint32_t brand;
3816a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (source->readAt(
3817a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                                chunkDataOffset + 4 * i, &brand, 4) < 4) {
3818a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        return false;
3819a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
3820a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3821a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    brand = ntohl(brand);
3822a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3823a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (isCompatibleBrand(brand)) {
3824a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        foundGoodFileType = true;
3825a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        break;
3826a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
3827a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
3828a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3829a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                if (!foundGoodFileType) {
3830a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    return false;
3831a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
3832a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
38331b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                break;
38341b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
3835a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3836a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            case FOURCC('m', 'o', 'o', 'v'):
3837a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            {
3838a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                moovAtomEndOffset = offset + chunkSize;
3839a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3840a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                done = true;
3841a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                break;
3842a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            }
3843a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3844a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            default:
3845a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                break;
38461b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
3847a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3848a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        offset += chunkSize;
38491b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
38501b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
3851a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (!foundGoodFileType) {
38521b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return false;
38531b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
38541b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
38551b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
38565a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber    *confidence = 0.4f;
38571b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
3858a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (moovAtomEndOffset >= 0) {
3859a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        *meta = new AMessage;
3860a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        (*meta)->setInt64("meta-data-size", moovAtomEndOffset);
3861a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
3862456caf3f5f0af673dc120c17c23635f40d8f5ac2Andreas Huber        ALOGV("found metadata size: %lld", moovAtomEndOffset);
3863a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    }
3864a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
38651b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return true;
38661b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
38671b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
38681b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberbool SniffMPEG4(
38695a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
3870a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        sp<AMessage> *meta) {
3871a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (BetterSniffMPEG4(source, mimeType, confidence, meta)) {
38721b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
38731b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
38741b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
38751b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    if (LegacySniffMPEG4(source, mimeType, confidence)) {
38765ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Identified supported mpeg4 through LegacySniffMPEG4.");
38771b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
38781b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
38791b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
38801b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
38811b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
38821b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
388320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
3884